mirror of
https://github.com/EssentialsX/Essentials.git
synced 2026-11-05 01:00:13 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d2a8ffba4 | ||
|
|
b781c1e924 | ||
|
|
19d6db0b4c | ||
|
|
02ced188c8 | ||
|
|
7f3b62a180 | ||
|
|
908b06570f | ||
|
|
d7e5c10b51 | ||
|
|
b2ae28b450 | ||
|
|
e558e7365a | ||
|
|
c32a0f975e | ||
|
|
ae1f1583c2 | ||
|
|
58eea1724f | ||
|
|
52c9ca8197 | ||
|
|
f26e1b2e29 | ||
|
|
f84a311c2b | ||
|
|
60129594a6 | ||
|
|
563d3fab4e | ||
|
|
1022f7a3ab | ||
|
|
d57094c0bc | ||
|
|
863b9cffc5 | ||
|
|
1921abd310 | ||
|
|
803d800bdd | ||
|
|
5276204cf2 | ||
|
|
697128bcf2 | ||
|
|
a1fa1e38f8 | ||
|
|
ed41790712 | ||
|
|
834ef4ea57 | ||
|
|
03ed9a5b41 | ||
|
|
d67dd46cdc | ||
|
|
694ed6e66f | ||
|
|
8a0526b1e5 | ||
|
|
a116e8630d | ||
|
|
8b2c7d7ad1 | ||
|
|
8d07c4bb0f | ||
|
|
fc3dabf8f5 | ||
|
|
cdd277da92 | ||
|
|
0d322e2c6b | ||
|
|
646b60a90b | ||
|
|
357cd6b246 | ||
|
|
a4fb02f3e6 | ||
|
|
2828901927 | ||
|
|
1e0f7cb984 | ||
|
|
52a4dd2c60 | ||
|
|
8323b47e40 | ||
|
|
14cdde009c | ||
|
|
1883e6adbc | ||
|
|
2f9659e7fc | ||
|
|
1a4f63915f | ||
|
|
dd3f4c2921 | ||
|
|
7ebb6359e5 | ||
|
|
069ebfcd5b | ||
|
|
991bc61b0c | ||
|
|
8194d1f747 | ||
|
|
ee7ea2ae39 | ||
|
|
3d23916ad5 | ||
|
|
e5b0c4c855 | ||
|
|
84fd45bd09 | ||
|
|
01883a6b18 | ||
|
|
fd49b70a69 | ||
|
|
3a737480ec | ||
|
|
384f63bf92 | ||
|
|
77dc87bb8e | ||
|
|
c716fc8236 | ||
|
|
c52c1fea9d | ||
|
|
e7c56b32a4 | ||
|
|
11e6d3ca7b | ||
|
|
75481925f7 | ||
|
|
ecb1850451 | ||
|
|
0f4af9e735 | ||
|
|
bf14b88600 | ||
|
|
43d84de2b2 | ||
|
|
25ad8ac9bd | ||
|
|
17051eab73 | ||
|
|
4dc994df3c | ||
|
|
996285c0e3 | ||
|
|
312d1699a8 | ||
|
|
b3238605cc | ||
|
|
b7a4bea52e | ||
|
|
ca71d93963 | ||
|
|
0936fe80bd | ||
|
|
520e8f991f | ||
|
|
3131cadf65 | ||
|
|
bfae6c5c69 | ||
|
|
52c500ee6d | ||
|
|
ba5a8becfc | ||
|
|
2a1957229f | ||
|
|
e6af246170 | ||
|
|
939e5c5a55 | ||
|
|
80bbf8c55b | ||
|
|
376abc4aab | ||
|
|
a7f4d6b16b | ||
|
|
e0d6040662 | ||
|
|
6ec4c97ddd | ||
|
|
db10678095 | ||
|
|
582a357752 | ||
|
|
8a1e7019a7 | ||
|
|
4414eea513 | ||
|
|
6e931b2b3b | ||
|
|
22a0d53cf2 | ||
|
|
20011b9996 | ||
|
|
879e70fb6b | ||
|
|
f91dfed5b4 | ||
|
|
767185ec32 | ||
|
|
4aa93a43db | ||
|
|
57529c4b7d | ||
|
|
dc7fb91939 | ||
|
|
e91ce0c44c | ||
|
|
f7cbc7b0d3 | ||
|
|
28d7abe642 | ||
|
|
0ca58ce4ba | ||
|
|
d75d3cd001 | ||
|
|
1eb5d8a459 | ||
|
|
b808511efe | ||
|
|
0897ef71f2 |
No files matched your search
@@ -7,14 +7,11 @@ contact_links:
|
||||
url: https://github.com/EssentialsX/Essentials/discussions/categories/q-a
|
||||
about: Visit the Q&A forum to search for previous help requests.
|
||||
- name: Check past feature suggestions
|
||||
url: https://github.com/EssentialsX/Essentials/discussions/categories/ideas-and-feature-suggestions
|
||||
url: https://github.com/EssentialsX/Essentials/issues?q=is%3Aissue+label%3A%22type%3A+enhancement%22
|
||||
about: Visit the Feature Suggestions forum to view and discuss existing feature suggestions.
|
||||
- name: Create help request
|
||||
url: https://github.com/EssentialsX/Essentials/discussions/new?category=q-a
|
||||
about: Create a support ticket to get help from developers.
|
||||
- name: Suggest a feature
|
||||
url: https://github.com/EssentialsX/Essentials/discussions/new?category=ideas-and-feature-suggestions
|
||||
about: Suggest new features for EssentialsX!
|
||||
- name: Get help from the community on Discord
|
||||
url: https://discord.gg/casfFyh
|
||||
about: Join the MOSS Discord for community-powered EssentialsX support!
|
||||
@@ -0,0 +1,40 @@
|
||||
name: Request a feature
|
||||
description: Suggest a feature you want to see in EssentialsX!
|
||||
labels: 'type: enhancement'
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
If you have a feature suggestion for EssentialsX, read the following tips:
|
||||
1. Fill out the template.
|
||||
This will help us understand what you're requesting and why you want us
|
||||
to add it.
|
||||
2. Keep it simple.
|
||||
Make sure it's easy to understand what you're requesting. A good way is
|
||||
to keep it to one request per GitHub issue, as we can then easily track
|
||||
feature requests.
|
||||
3. Check whether it has already been asked or added.
|
||||
You can search the issue tracker to see if your feature has already been
|
||||
requested at https://github.com/EssentialsX/Essentials/issues. You can
|
||||
also check the changelogs to see if the feature was recently added:
|
||||
https://github.com/EssentialsX/Essentials/releases
|
||||
4. Ask yourself: "Does this belong in EssentialsX?"
|
||||
There are lots of features that we reject because most servers won't
|
||||
need or use them. If your feature is very specific or already exists in
|
||||
another plugin, it might not be a good fit for EssentialsX.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: Explain what you should expect to happen.
|
||||
placeholder: |
|
||||
What feature are you suggesting?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: How the feature is useful
|
||||
description: Explain what actually happens.
|
||||
placeholder: |
|
||||
How is the feature useful to players, server owners and/or developers?
|
||||
validations:
|
||||
required: true
|
||||
@@ -5,6 +5,9 @@ on:
|
||||
branches:
|
||||
- 2.x
|
||||
- dev/*
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -13,26 +16,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Git repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Restore Gradle cache
|
||||
uses: actions/cache@v2
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: 16
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
@@ -40,7 +35,7 @@ jobs:
|
||||
./gradlew build --stacktrace
|
||||
|
||||
- name: Archive plugin jars on GitHub
|
||||
uses: actions/upload-artifact@master
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: EssentialsX plugin jars
|
||||
path: jars/
|
||||
@@ -54,22 +49,43 @@ jobs:
|
||||
./gradlew publish
|
||||
|
||||
- name: Prepare Javadocs
|
||||
if: ${{ success() && github.event_name == 'push' && github.repository == 'EssentialsX/Essentials' && github.ref == 'refs/heads/2.x' }}
|
||||
run: |
|
||||
mv Essentials/build/docs/javadoc/ javadocs/
|
||||
cp -r EssentialsAntiBuild/build/docs/javadoc/ javadocs/EssentialsAntiBuild/
|
||||
cp -r EssentialsChat/build/docs/javadoc/ javadocs/EssentialsChat/
|
||||
cp -r EssentialsDiscord/build/docs/javadoc/ javadocs/EssentialsDiscord/
|
||||
cp -r EssentialsDiscordLink/build/docs/javadoc/ javadocs/EssentialsDiscordLink/
|
||||
cp -r EssentialsGeoIP/build/docs/javadoc/ javadocs/EssentialsGeoIP/
|
||||
cp -r EssentialsProtect/build/docs/javadoc/ javadocs/EssentialsProtect/
|
||||
cp -r EssentialsSpawn/build/docs/javadoc/ javadocs/EssentialsSpawn/
|
||||
cp -r EssentialsXMPP/build/docs/javadoc/ javadocs/EssentialsXMPP/
|
||||
|
||||
- name: Deploy Javadocs
|
||||
if: ${{ success() && github.event_name == 'push' && github.repository == 'EssentialsX/Essentials' && github.ref == 'refs/heads/2.x' }}
|
||||
uses: netlify/actions/cli@master
|
||||
- name: Archive Javadocs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
args: deploy --dir=javadocs/ --prod --message="GitHubActionsDeploy"
|
||||
name: javadocs
|
||||
path: javadocs/
|
||||
|
||||
publish-jd:
|
||||
name: Publish Javadocs
|
||||
needs: build
|
||||
if: ${{ github.event_name == 'push' && github.repository == 'EssentialsX/Essentials' && github.ref == 'refs/heads/2.x' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Download Javadocs
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: javadocs
|
||||
path: javadocs/
|
||||
|
||||
- name: Deploy Javadocs
|
||||
run: npx netlify-cli deploy --dir=javadocs/ --prod --message="GitHubActionsDeploy"
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_JD_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_JD_2X_SITE_ID }}
|
||||
@@ -18,26 +18,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Git repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Restore Gradle cache
|
||||
uses: actions/cache@v2
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'adopt'
|
||||
java-version: 16
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
@@ -45,7 +37,7 @@ jobs:
|
||||
./gradlew build --stacktrace
|
||||
|
||||
- name: Archive plugin jars on GitHub
|
||||
uses: actions/upload-artifact@master
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: EssentialsX plugin jars
|
||||
path: jars/
|
||||
@@ -15,6 +15,8 @@
|
||||
/Essentials/kits.yml
|
||||
/Essentials/userdata/testplayer1.yml
|
||||
/Essentials/usermap.csv
|
||||
/Essentials/usermap.bin
|
||||
/Essentials/uuids.bin
|
||||
|
||||
# Build files
|
||||
.gradle/
|
||||
|
||||
@@ -28,8 +28,8 @@ public class BalanceTopImpl implements BalanceTop {
|
||||
private void calculateBalanceTopMap() {
|
||||
final List<Entry> entries = new LinkedList<>();
|
||||
BigDecimal newTotal = BigDecimal.ZERO;
|
||||
for (UUID u : ess.getUserMap().getAllUniqueUsers()) {
|
||||
final User user = ess.getUserMap().getUser(u);
|
||||
for (UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user != null) {
|
||||
if (!ess.getSettings().isNpcsInBalanceRanking() && user.isNPC()) {
|
||||
// Don't list NPCs in output
|
||||
@@ -40,7 +40,7 @@ public class BalanceTopImpl implements BalanceTop {
|
||||
user.updateMoneyCache(userMoney);
|
||||
newTotal = newTotal.add(userMoney);
|
||||
final String name;
|
||||
if (user.getBase() instanceof OfflinePlayer) {
|
||||
if (user.getBase() instanceof OfflinePlayerStub) {
|
||||
name = user.getLastAccountName();
|
||||
} else if (user.isHidden()) {
|
||||
name = user.getName();
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.SimpleTextInput;
|
||||
import com.earth2me.essentials.updatecheck.UpdateChecker;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
@@ -143,7 +144,7 @@ import static com.earth2me.essentials.I18n.tl;
|
||||
public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
private static final Logger BUKKIT_LOGGER = Logger.getLogger("Essentials");
|
||||
private static Logger LOGGER = null;
|
||||
private final transient TNTExplodeListener tntListener = new TNTExplodeListener(this);
|
||||
private final transient TNTExplodeListener tntListener = new TNTExplodeListener();
|
||||
private final transient Set<String> vanishedPlayers = new LinkedHashSet<>();
|
||||
private transient ISettings settings;
|
||||
private transient Jails jails;
|
||||
@@ -155,7 +156,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
private transient CustomItemResolver customItemResolver;
|
||||
private transient PermissionsHandler permissionsHandler;
|
||||
private transient AlternativeCommandsHandler alternativeCommandsHandler;
|
||||
private transient UserMap userMap;
|
||||
@Deprecated
|
||||
private transient UserMap legacyUserMap;
|
||||
private transient ModernUserMap userMap;
|
||||
private transient BalanceTopImpl balanceTop;
|
||||
private transient ExecuteTimer execTimer;
|
||||
private transient MailService mail;
|
||||
@@ -222,7 +225,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
LOGGER.log(Level.INFO, dataFolder.toString());
|
||||
settings = new Settings(this);
|
||||
mail = new MailServiceImpl(this);
|
||||
userMap = new UserMap(this);
|
||||
userMap = new ModernUserMap(this);
|
||||
balanceTop = new BalanceTopImpl(this);
|
||||
permissionsHandler = new PermissionsHandler(this, false);
|
||||
Economy.setEss(this);
|
||||
@@ -301,11 +304,14 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
confList.add(settings);
|
||||
execTimer.mark("Settings");
|
||||
|
||||
upgrade.preModules();
|
||||
execTimer.mark("Upgrade2");
|
||||
|
||||
mail = new MailServiceImpl(this);
|
||||
execTimer.mark("Init(Mail)");
|
||||
|
||||
userMap = new UserMap(this);
|
||||
confList.add(userMap);
|
||||
userMap = new ModernUserMap(this);
|
||||
legacyUserMap = new UserMap(userMap);
|
||||
execTimer.mark("Init(Usermap)");
|
||||
|
||||
balanceTop = new BalanceTopImpl(this);
|
||||
@@ -317,7 +323,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
execTimer.mark("Kits");
|
||||
|
||||
upgrade.afterSettings();
|
||||
execTimer.mark("Upgrade2");
|
||||
execTimer.mark("Upgrade3");
|
||||
|
||||
warps = new Warps(this.getDataFolder());
|
||||
confList.add(warps);
|
||||
@@ -588,7 +594,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
|
||||
Economy.setEss(null);
|
||||
Trade.closeLog();
|
||||
getUserMap().getUUIDMap().shutdown();
|
||||
getUsers().shutdown();
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
@@ -948,17 +954,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
//This will return null if there is not a match.
|
||||
@Override
|
||||
public User getOfflineUser(final String name) {
|
||||
final User user = userMap.getUser(name);
|
||||
if (user != null && user.getBase() instanceof OfflinePlayer) {
|
||||
//This code should attempt to use the last known name of a user, if Bukkit returns name as null.
|
||||
final String lastName = user.getLastAccountName();
|
||||
if (lastName != null) {
|
||||
((OfflinePlayer) user.getBase()).setName(lastName);
|
||||
} else {
|
||||
((OfflinePlayer) user.getBase()).setName(name);
|
||||
}
|
||||
}
|
||||
return user;
|
||||
return userMap.getUser(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1046,7 +1042,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return true;
|
||||
}
|
||||
|
||||
return interactor.getBase().canSee(interactee.getBase());
|
||||
return !interactee.isHiddenFrom(interactor.getBase());
|
||||
}
|
||||
|
||||
//This will create a new user if there is not a match.
|
||||
@@ -1061,14 +1057,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return null;
|
||||
}
|
||||
|
||||
User user = userMap.getUser(base.getUniqueId());
|
||||
final User user = userMap.getUser(base);
|
||||
|
||||
if (user == null) {
|
||||
if (getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, "Constructing new userfile from base player " + base.getName());
|
||||
}
|
||||
user = new User(base, this);
|
||||
} else {
|
||||
if (base.getClass() != UUIDPlayer.class || user.getBase() == null) {
|
||||
user.update(base);
|
||||
}
|
||||
return user;
|
||||
@@ -1182,11 +1173,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
return this.getScheduler().scheduleSyncRepeatingTask(this, run, delay, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TNTExplodeListener getTNTListener() {
|
||||
return tntListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionsHandler getPermissionsHandler() {
|
||||
return permissionsHandler;
|
||||
@@ -1203,7 +1189,13 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public UserMap getUserMap() {
|
||||
return legacyUserMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModernUserMap getUsers() {
|
||||
return userMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.GameMode;
|
||||
@@ -45,7 +46,7 @@ public class EssentialsBlockListener implements Listener {
|
||||
if (is != null && is.getType() != null && !MaterialUtil.isAir(is.getType())) {
|
||||
final ItemStack cloneIs = is.clone();
|
||||
cloneIs.setAmount(1);
|
||||
user.getBase().getInventory().addItem(cloneIs);
|
||||
Inventories.addItem(user.getBase(), cloneIs);
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Location;
|
||||
@@ -52,12 +52,12 @@ public class EssentialsEntityListener implements Listener {
|
||||
if (eDefend instanceof Player) {
|
||||
onPlayerVsPlayerDamage(event, (Player) eDefend, attacker);
|
||||
} else if (eDefend instanceof Ageable) {
|
||||
final ItemStack hand = attacker.getBase().getItemInHand();
|
||||
final ItemStack hand = Inventories.getItemInMainHand(attacker.getBase());
|
||||
if (ess.getSettings().isMilkBucketEasterEggEnabled()
|
||||
&& hand != null && hand.getType() == Material.MILK_BUCKET) {
|
||||
((Ageable) eDefend).setBaby();
|
||||
hand.setType(Material.BUCKET);
|
||||
attacker.getBase().setItemInHand(hand);
|
||||
Inventories.setItemInMainHand(attacker.getBase(), hand);
|
||||
attacker.getBase().updateInventory();
|
||||
event.setCancelled(true);
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public class EssentialsEntityListener implements Listener {
|
||||
}
|
||||
|
||||
private void onPlayerVsPlayerPowertool(final EntityDamageByEntityEvent event, final Player defender, final User attacker) {
|
||||
final List<String> commandList = attacker.getPowertool(attacker.getBase().getItemInHand());
|
||||
final List<String> commandList = attacker.getPowertool(Inventories.getItemInHand(attacker.getBase()));
|
||||
if (commandList != null && !commandList.isEmpty()) {
|
||||
for (final String tempCommand : commandList) {
|
||||
final String command = powertoolPlayer.matcher(tempCommand).replaceAll(defender.getName());
|
||||
@@ -196,73 +196,23 @@ public class EssentialsEntityListener implements Listener {
|
||||
final ISettings.KeepInvPolicy vanish = ess.getSettings().getVanishingItemsPolicy();
|
||||
final ISettings.KeepInvPolicy bind = ess.getSettings().getBindingItemsPolicy();
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_11_2_R01) && (vanish != ISettings.KeepInvPolicy.KEEP || bind != ISettings.KeepInvPolicy.KEEP)) {
|
||||
for (final ItemStack stack : event.getEntity().getInventory()) {
|
||||
if (stack != null && !MaterialUtil.isAir(stack.getType())) {
|
||||
if (stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE)) {
|
||||
if (vanish == ISettings.KeepInvPolicy.DELETE) {
|
||||
event.getEntity().getInventory().remove(stack);
|
||||
} else if (vanish == ISettings.KeepInvPolicy.DROP) {
|
||||
event.getDrops().add(stack);
|
||||
event.getEntity().getInventory().remove(stack);
|
||||
}
|
||||
}
|
||||
if (stack.getEnchantments().containsKey(Enchantment.BINDING_CURSE)) {
|
||||
if (bind == ISettings.KeepInvPolicy.DELETE) {
|
||||
event.getEntity().getInventory().remove(stack);
|
||||
} else if (bind == ISettings.KeepInvPolicy.DROP) {
|
||||
event.getEntity().getInventory().remove(stack);
|
||||
event.getDrops().add(stack);
|
||||
}
|
||||
Inventories.removeItems(user.getBase(), stack -> {
|
||||
if (vanish != ISettings.KeepInvPolicy.KEEP && stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE)) {
|
||||
if (vanish == ISettings.KeepInvPolicy.DROP) {
|
||||
event.getDrops().add(stack.clone());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Now check armor
|
||||
final ItemStack[] armor = event.getEntity().getInventory().getArmorContents();
|
||||
for (int i = 0; i < armor.length; i++) {
|
||||
final ItemStack stack = armor[i];
|
||||
if (stack != null && !MaterialUtil.isAir(stack.getType())) {
|
||||
if (stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE)) {
|
||||
if (vanish == ISettings.KeepInvPolicy.DELETE) {
|
||||
armor[i] = null;
|
||||
} else if (vanish == ISettings.KeepInvPolicy.DROP) {
|
||||
if (!event.getDrops().contains(stack)) {
|
||||
event.getDrops().add(stack);
|
||||
}
|
||||
armor[i] = null;
|
||||
}
|
||||
}
|
||||
if (stack.getEnchantments().containsKey(Enchantment.BINDING_CURSE)) {
|
||||
if (bind == ISettings.KeepInvPolicy.DELETE) {
|
||||
armor[i] = null;
|
||||
} else if (bind == ISettings.KeepInvPolicy.DROP) {
|
||||
if (!event.getDrops().contains(stack)) {
|
||||
event.getDrops().add(stack);
|
||||
}
|
||||
armor[i] = null;
|
||||
}
|
||||
if (bind != ISettings.KeepInvPolicy.KEEP && stack.getEnchantments().containsKey(Enchantment.BINDING_CURSE)) {
|
||||
if (bind == ISettings.KeepInvPolicy.DROP) {
|
||||
event.getDrops().add(stack.clone());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
event.getEntity().getInventory().setArmorContents(armor);
|
||||
|
||||
// Now check offhand
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01)) {
|
||||
final ItemStack stack = event.getEntity().getInventory().getItemInOffHand();
|
||||
//noinspection ConstantConditions
|
||||
if (stack != null && !MaterialUtil.isAir(stack.getType())) {
|
||||
final boolean isVanish = stack.getEnchantments().containsKey(Enchantment.VANISHING_CURSE);
|
||||
final boolean isBind = stack.getEnchantments().containsKey(Enchantment.BINDING_CURSE);
|
||||
if (isVanish || isBind) {
|
||||
event.getEntity().getInventory().setItemInOffHand(null);
|
||||
if ((isVanish && vanish == ISettings.KeepInvPolicy.DROP) || (isBind && bind == ISettings.KeepInvPolicy.DROP)) {
|
||||
if (!event.getDrops().contains(stack)) {
|
||||
event.getDrops().add(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.commands.Commandfireball;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.TextInput;
|
||||
@@ -120,6 +121,15 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGameEventEvent() {
|
||||
try {
|
||||
Class.forName("org.bukkit.event.block.BlockReceiveGameEvent");
|
||||
return true;
|
||||
} catch (final ClassNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void registerEvents() {
|
||||
ess.getServer().getPluginManager().registerEvents(this, ess);
|
||||
|
||||
@@ -127,6 +137,10 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
ess.getServer().getPluginManager().registerEvents(new ArrowPickupListener(), ess);
|
||||
}
|
||||
|
||||
if (isGameEventEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new SculkListener1_17(), ess);
|
||||
}
|
||||
|
||||
if (isEntityPickupEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new PickupListener1_12(), ess);
|
||||
} else {
|
||||
@@ -192,17 +206,26 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ess.getSettings().cancelAfkOnMove() && !ess.getSettings().getFreezeAfkPlayers()) {
|
||||
event.getHandlers().unregister(this);
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Unregistering move listener");
|
||||
if (user.isFreeze()) {
|
||||
final Location from = event.getFrom();
|
||||
final Location to = event.getTo().clone();
|
||||
to.setX(from.getX());
|
||||
to.setY(from.getY());
|
||||
to.setZ(from.getZ());
|
||||
try {
|
||||
event.setTo(LocationUtil.getSafeDestination(ess, to));
|
||||
} catch (final Exception ex) {
|
||||
event.setTo(to);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (!ess.getSettings().cancelAfkOnMove() && !ess.getSettings().getFreezeAfkPlayers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.isAfk() && ess.getSettings().getFreezeAfkPlayers()) {
|
||||
final Location from = event.getFrom();
|
||||
final Location origTo = event.getTo();
|
||||
@@ -308,6 +331,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
|
||||
ess.getBackup().onPlayerJoin();
|
||||
final User dUser = ess.getUser(player);
|
||||
dUser.update(player);
|
||||
|
||||
dUser.startTransaction();
|
||||
if (dUser.isNPC()) {
|
||||
@@ -367,7 +391,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
} else if (ess.getSettings().isCustomJoinMessage()) {
|
||||
final String msg = (newUsername ? ess.getSettings().getCustomNewUsernameMessage() : ess.getSettings().getCustomJoinMessage())
|
||||
.replace("{PLAYER}", player.getDisplayName()).replace("{USERNAME}", player.getName())
|
||||
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUserMap().getUniqueUsers()))
|
||||
.replace("{UNIQUE}", NumberFormat.getInstance().format(ess.getUsers().getUserCount()))
|
||||
.replace("{ONLINE}", NumberFormat.getInstance().format(ess.getOnlinePlayers().size()))
|
||||
.replace("{UPTIME}", DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()))
|
||||
.replace("{PREFIX}", FormatUtil.replaceFormat(ess.getPermissionsHandler().getPrefix(player)))
|
||||
@@ -527,6 +551,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
public void onPlayerLogin(final PlayerLoginEvent event) {
|
||||
if (event.getResult() == Result.KICK_FULL) {
|
||||
final User kfuser = ess.getUser(event.getPlayer());
|
||||
kfuser.update(event.getPlayer());
|
||||
if (kfuser.isAuthorized("essentials.joinfullserver")) {
|
||||
event.allow();
|
||||
return;
|
||||
@@ -557,7 +582,7 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
final ItemStack stack = new ItemStack(Material.EGG, 1);
|
||||
if (user.hasUnlimited(stack)) {
|
||||
user.getBase().getInventory().addItem(stack);
|
||||
Inventories.addItem(user.getBase(), stack);
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
}
|
||||
@@ -650,7 +675,8 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
}
|
||||
|
||||
if (ess.getSettings().isCommandCooldownsEnabled()
|
||||
&& !user.isAuthorized("essentials.commandcooldowns.bypass")) {
|
||||
&& !user.isAuthorized("essentials.commandcooldowns.bypass")
|
||||
&& (pluginCommand == null || !user.isAuthorized("essentials.commandcooldowns.bypass." + pluginCommand.getName()))) {
|
||||
final int argStartIndex = effectiveCommand.indexOf(" ");
|
||||
final String args = argStartIndex == -1 ? "" // No arguments present
|
||||
: " " + effectiveCommand.substring(argStartIndex); // arguments start at argStartIndex; substring from there.
|
||||
@@ -988,6 +1014,15 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
private final class SculkListener1_17 implements Listener {
|
||||
@EventHandler
|
||||
public void onGameEvent(final org.bukkit.event.block.BlockReceiveGameEvent event) {
|
||||
if (event.getEntity() instanceof Player && ess.getUser((Player) event.getEntity()).isVanished()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class CommandSendFilter implements CommandSendListenerProvider.Filter {
|
||||
@Override
|
||||
public Predicate<String> apply(Player player) {
|
||||
|
||||
@@ -4,9 +4,9 @@ import com.earth2me.essentials.config.ConfigurateUtil;
|
||||
import com.earth2me.essentials.config.EssentialsConfiguration;
|
||||
import com.earth2me.essentials.config.EssentialsUserConfiguration;
|
||||
import com.earth2me.essentials.craftbukkit.BanLookup;
|
||||
import com.earth2me.essentials.userstorage.ModernUUIDCache;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import net.ess3.api.IEssentials;
|
||||
@@ -31,10 +31,10 @@ import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -47,13 +47,12 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class EssentialsUpgrade {
|
||||
private static final FileFilter YML_FILTER = pathname -> pathname.isFile() && pathname.getName().endsWith(".yml");
|
||||
public static final FileFilter YML_FILTER = pathname -> pathname.isFile() && pathname.getName().endsWith(".yml");
|
||||
private static final String PATTERN_CONFIG_UUID_REGEX = "(?mi)^uuid:\\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\s*$";
|
||||
private static final Pattern PATTERN_CONFIG_UUID = Pattern.compile(PATTERN_CONFIG_UUID_REGEX);
|
||||
private static final String PATTERN_CONFIG_NAME_REGEX = "(?mi)^lastAccountName:\\s*[\"\']?(\\w+)[\"\']?\\s*$";
|
||||
@@ -93,7 +92,6 @@ public class EssentialsUpgrade {
|
||||
final int showProgress = countFiles % 250;
|
||||
|
||||
if (showProgress == 0) {
|
||||
ess.getUserMap().getUUIDMap().forceWriteUUIDMap();
|
||||
ess.getLogger().info("Converted " + countFiles + "/" + userdir.list().length);
|
||||
}
|
||||
|
||||
@@ -103,7 +101,8 @@ public class EssentialsUpgrade {
|
||||
final EssentialsUserConfiguration config;
|
||||
UUID uuid = null;
|
||||
try {
|
||||
uuid = UUID.fromString(name);
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
UUID.fromString(name);
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
final File file = new File(userdir, string);
|
||||
final EssentialsConfiguration conf = new EssentialsConfiguration(file);
|
||||
@@ -115,6 +114,7 @@ public class EssentialsUpgrade {
|
||||
|
||||
final String uuidString = conf.getString(uuidConf, null);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
for (int i = 0; i < 4; i++) {
|
||||
try {
|
||||
uuid = UUID.fromString(uuidString);
|
||||
@@ -122,7 +122,7 @@ public class EssentialsUpgrade {
|
||||
break;
|
||||
} catch (final Exception ex2) {
|
||||
if (conf.getBoolean("npc", false)) {
|
||||
uuid = UUID.nameUUIDFromBytes(("NPC:" + name).getBytes(Charsets.UTF_8));
|
||||
uuid = UUID.nameUUIDFromBytes(("NPC:" + (ess.getSettings().isSafeUsermap() ? StringUtil.safeString(name) : name)).getBytes(Charsets.UTF_8));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -130,23 +130,24 @@ public class EssentialsUpgrade {
|
||||
uuid = player.getUniqueId();
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
if (uuid != null) {
|
||||
countBukkit++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
if (uuid != null) {
|
||||
conf.blockingSave();
|
||||
config = new EssentialsUserConfiguration(name, uuid, new File(userdir, uuid + ".yml"));
|
||||
config.convertLegacyFile();
|
||||
ess.getUserMap().trackUUID(uuid, name, false);
|
||||
ess.getUsers().loadUncachedUser(uuid);
|
||||
continue;
|
||||
}
|
||||
countFails++;
|
||||
}
|
||||
}
|
||||
ess.getUserMap().getUUIDMap().forceWriteUUIDMap();
|
||||
|
||||
ess.getLogger().info("Converted " + countFiles + "/" + countFiles + ". Conversion complete.");
|
||||
ess.getLogger().info("Converted via cache: " + countEssCache + " :: Converted via lookup: " + countBukkit + " :: Failed to convert: " + countFails);
|
||||
@@ -913,74 +914,76 @@ public class EssentialsUpgrade {
|
||||
Bukkit.getBanList(BanList.Type.NAME).addBan(playerName, banReason, banTimeout == 0 ? null : new Date(banTimeout), Console.NAME);
|
||||
}
|
||||
|
||||
private void repairUserMap() {
|
||||
if (doneFile.getBoolean("userMapRepaired", false)) {
|
||||
public void generateUidCache() {
|
||||
if (doneFile.getBoolean("newUidCacheBuilt", false)) {
|
||||
return;
|
||||
}
|
||||
ess.getLogger().info("Starting usermap repair");
|
||||
|
||||
final File usermapFile = new File(ess.getDataFolder(), "usermap.bin");
|
||||
final File uidsFile = new File(ess.getDataFolder(), "uuids.bin");
|
||||
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdataFolder.isDirectory()) {
|
||||
|
||||
if (!userdataFolder.isDirectory() || usermapFile.exists() || uidsFile.exists()) {
|
||||
ess.getLogger().warning("Missing userdata folder, aborting");
|
||||
doneFile.setProperty("newUidCacheBuilt", true);
|
||||
doneFile.save();
|
||||
return;
|
||||
}
|
||||
final File[] files = userdataFolder.listFiles(YML_FILTER);
|
||||
|
||||
final DecimalFormat format = new DecimalFormat("#0.00");
|
||||
final Map<String, UUID> names = Maps.newHashMap();
|
||||
|
||||
for (int index = 0; index < files.length; index++) {
|
||||
final File file = files[index];
|
||||
try {
|
||||
UUID uuid = null;
|
||||
final String filename = file.getName();
|
||||
final String configData = new String(java.nio.file.Files.readAllBytes(file.toPath()), Charsets.UTF_8);
|
||||
|
||||
if (filename.length() > 36) {
|
||||
try {
|
||||
// ".yml" ending has 4 chars...
|
||||
uuid = UUID.fromString(filename.substring(0, filename.length() - 4));
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
final Matcher uuidMatcher = PATTERN_CONFIG_UUID.matcher(configData);
|
||||
if (uuidMatcher.find()) {
|
||||
try {
|
||||
uuid = UUID.fromString(uuidMatcher.group(1));
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uuid == null) {
|
||||
// Don't import
|
||||
continue;
|
||||
}
|
||||
|
||||
final Matcher nameMatcher = PATTERN_CONFIG_NAME.matcher(configData);
|
||||
if (nameMatcher.find()) {
|
||||
final String username = nameMatcher.group(1);
|
||||
if (username != null && username.length() > 0) {
|
||||
names.put(StringUtil.safeString(username), uuid);
|
||||
}
|
||||
}
|
||||
|
||||
if (index % 1000 == 0) {
|
||||
ess.getLogger().info("Reading: " + format.format((100d * (double) index) / files.length)
|
||||
+ "%");
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while reading file: ", e);
|
||||
try {
|
||||
if (!usermapFile.createNewFile() || !uidsFile.createNewFile()) {
|
||||
ess.getLogger().warning("Couldn't create usermap.bin or uuids.bin, aborting");
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<UUID, Long> uuids = new HashMap<>();
|
||||
final Map<String, UUID> nameToUuidMap = new HashMap<>();
|
||||
|
||||
final File[] files = userdataFolder.listFiles(YML_FILTER);
|
||||
if (files != null) {
|
||||
for (final File file : files) {
|
||||
try {
|
||||
final String fileName = file.getName();
|
||||
final UUID uuid = UUID.fromString(fileName.substring(0, fileName.length() - 4));
|
||||
final EssentialsConfiguration config = new EssentialsConfiguration(file);
|
||||
config.load();
|
||||
String name = config.getString("last-account-name", null);
|
||||
name = ess.getSettings().isSafeUsermap() ? StringUtil.safeString(name) : name;
|
||||
final long time = config.getLong("timestamps.logout", 0L);
|
||||
|
||||
if (name != null) {
|
||||
if (nameToUuidMap.containsKey(name)) {
|
||||
final UUID oldUuid = nameToUuidMap.get(name);
|
||||
if (oldUuid.version() < uuid.version() || (oldUuid.version() == uuid.version() && uuids.get(oldUuid) < time)) {
|
||||
ess.getLogger().warning("New UUID found for " + name + ": " + uuid + " (old: " + oldUuid + "). Replacing.");
|
||||
uuids.remove(oldUuid);
|
||||
} else {
|
||||
ess.getLogger().warning("Found UUID for " + name + ": " + uuid + " (old: " + oldUuid + "). Skipping.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uuids.put(uuid, time);
|
||||
nameToUuidMap.put(name, uuid);
|
||||
}
|
||||
} catch (IllegalArgumentException | IndexOutOfBoundsException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nameToUuidMap.isEmpty()) {
|
||||
ModernUUIDCache.writeNameUuidMap(usermapFile, nameToUuidMap);
|
||||
}
|
||||
|
||||
if (!uuids.isEmpty()) {
|
||||
ModernUUIDCache.writeUuidCache(uidsFile, uuids.keySet());
|
||||
}
|
||||
|
||||
doneFile.setProperty("newUidCacheBuilt", true);
|
||||
doneFile.save();
|
||||
} catch (final IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while generating initial uuids/names cache", e);
|
||||
}
|
||||
|
||||
ess.getUserMap().getNames().putAll(names);
|
||||
ess.getUserMap().reloadConfig();
|
||||
|
||||
doneFile.setProperty("userMapRepaired", true);
|
||||
doneFile.save();
|
||||
ess.getLogger().info("Completed usermap repair.");
|
||||
}
|
||||
|
||||
public void beforeSettings() {
|
||||
@@ -991,6 +994,10 @@ public class EssentialsUpgrade {
|
||||
moveMotdRulesToFile("rules");
|
||||
}
|
||||
|
||||
public void preModules() {
|
||||
generateUidCache();
|
||||
}
|
||||
|
||||
public void afterSettings() {
|
||||
sanitizeAllUserFilenames();
|
||||
updateUsersPowerToolsFormat();
|
||||
@@ -1001,7 +1008,6 @@ public class EssentialsUpgrade {
|
||||
uuidFileChange();
|
||||
banFormatChange();
|
||||
warnMetrics();
|
||||
repairUserMap();
|
||||
convertIgnoreList();
|
||||
convertStupidCamelCaseUserdataKeys();
|
||||
convertMailList();
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.commands.PlayerNotFoundException;
|
||||
import com.earth2me.essentials.perm.PermissionsHandler;
|
||||
import com.earth2me.essentials.updatecheck.UpdateChecker;
|
||||
import com.earth2me.essentials.userstorage.IUserMap;
|
||||
import net.ess3.nms.refl.providers.ReflOnlineModeProvider;
|
||||
import net.ess3.provider.ContainerProvider;
|
||||
import net.ess3.provider.FormattedCommandAliasProvider;
|
||||
@@ -109,8 +110,6 @@ public interface IEssentials extends Plugin {
|
||||
|
||||
int scheduleSyncRepeatingTask(Runnable run, long delay, long period);
|
||||
|
||||
TNTExplodeListener getTNTListener();
|
||||
|
||||
PermissionsHandler getPermissionsHandler();
|
||||
|
||||
AlternativeCommandsHandler getAlternativeCommandsHandler();
|
||||
@@ -119,6 +118,9 @@ public interface IEssentials extends Plugin {
|
||||
|
||||
IItemDb getItemDb();
|
||||
|
||||
IUserMap getUsers();
|
||||
|
||||
@Deprecated
|
||||
UserMap getUserMap();
|
||||
|
||||
BalanceTop getBalanceTop();
|
||||
|
||||
@@ -282,6 +282,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
int getMaxUserCacheCount();
|
||||
|
||||
long getMaxUserCacheValueExpiry();
|
||||
|
||||
boolean allowSilentJoinQuit();
|
||||
|
||||
boolean isCustomJoinMessage();
|
||||
|
||||
@@ -155,6 +155,8 @@ public interface IUser {
|
||||
|
||||
void delHome(String name) throws Exception;
|
||||
|
||||
void renameHome(String name, String newName) throws Exception;
|
||||
|
||||
boolean hasHome();
|
||||
|
||||
Location getLastLocation();
|
||||
@@ -330,4 +332,12 @@ public interface IUser {
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
|
||||
List<String> getPastUsernames();
|
||||
|
||||
void addPastUsername(String username);
|
||||
|
||||
boolean isFreeze();
|
||||
|
||||
void setFreeze(boolean freeze);
|
||||
}
|
||||
@@ -203,6 +203,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
private class JailListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailBlockBreak(final BlockBreakEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed() && !user.isAuthorized("essentials.jail.allow-break")) {
|
||||
event.setCancelled(true);
|
||||
@@ -211,6 +215,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailBlockPlace(final BlockPlaceEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed() && !user.isAuthorized("essentials.jail.allow-place")) {
|
||||
event.setCancelled(true);
|
||||
@@ -219,6 +227,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailBlockDamage(final BlockDamageEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed() && !user.isAuthorized("essentials.jail.allow-block-damage")) {
|
||||
event.setCancelled(true);
|
||||
@@ -232,6 +244,9 @@ public class Jails implements net.ess3.api.IJails {
|
||||
}
|
||||
final Entity damager = event.getDamager();
|
||||
if (damager.getType() == EntityType.PLAYER) {
|
||||
if (shouldIgnore((Player) damager)) {
|
||||
return;
|
||||
}
|
||||
final User user = ess.getUser((Player) damager);
|
||||
if (user != null && user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
@@ -241,6 +256,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailPlayerInteract(final PlayerInteractEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed() && !user.isAuthorized("essentials.jail.allow-interact")) {
|
||||
event.setCancelled(true);
|
||||
@@ -249,6 +268,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onJailPlayerGameModeChange(final PlayerGameModeChangeEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (user.isJailed()) {
|
||||
event.setCancelled(true);
|
||||
@@ -257,6 +280,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onJailPlayerRespawn(final PlayerRespawnEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (!user.isJailed() || user.getJail() == null || user.getJail().isEmpty()) {
|
||||
return;
|
||||
@@ -275,6 +302,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onJailPlayerTeleport(final PlayerTeleportEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
if (!user.isJailed() || user.getJail() == null || user.getJail().isEmpty()) {
|
||||
return;
|
||||
@@ -294,6 +325,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onJailPlayerJoin(final PlayerJoinEvent event) {
|
||||
if (shouldIgnore(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
user.checkJailTimeout(currentTime);
|
||||
@@ -318,5 +353,10 @@ public class Jails implements net.ess3.api.IJails {
|
||||
future.completeExceptionally(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldIgnore(final Player base) {
|
||||
// Ignore Citizens NPCs
|
||||
return base.getUniqueId().version() == 2 || base.hasMetadata("NPC");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,23 +2,23 @@ package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.Trade.OverflowType;
|
||||
import com.earth2me.essentials.commands.NoChargeException;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.textreader.IText;
|
||||
import com.earth2me.essentials.textreader.KeywordReplacer;
|
||||
import com.earth2me.essentials.textreader.SimpleTextInput;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.events.KitClaimEvent;
|
||||
import net.essentialsx.api.v2.events.KitPreExpandItemsEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
@@ -214,57 +214,38 @@ public class Kit {
|
||||
stack = metaStack.getItemStack();
|
||||
}
|
||||
|
||||
if (autoEquip) {
|
||||
final Material material = stack.getType();
|
||||
final PlayerInventory inventory = user.getBase().getInventory();
|
||||
if (MaterialUtil.isHelmet(material) && isEmptyStack(inventory.getHelmet())) {
|
||||
inventory.setHelmet(stack);
|
||||
continue;
|
||||
} else if (MaterialUtil.isChestplate(material) && isEmptyStack(inventory.getChestplate())) {
|
||||
inventory.setChestplate(stack);
|
||||
continue;
|
||||
} else if (MaterialUtil.isLeggings(material) && isEmptyStack(inventory.getLeggings())) {
|
||||
inventory.setLeggings(stack);
|
||||
continue;
|
||||
} else if (MaterialUtil.isBoots(material) && isEmptyStack(inventory.getBoots())) {
|
||||
inventory.setBoots(stack);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
itemList.add(stack);
|
||||
}
|
||||
|
||||
final Map<Integer, ItemStack> overfilled;
|
||||
final boolean allowOversizedStacks = user.isAuthorized("essentials.oversizedstacks");
|
||||
final int maxStackSize = user.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0;
|
||||
final boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull();
|
||||
if (isDropItemsIfFull) {
|
||||
if (allowOversizedStacks) {
|
||||
overfilled = InventoryWorkaround.addOversizedItems(user.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), itemList.toArray(new ItemStack[0]));
|
||||
} else {
|
||||
overfilled = InventoryWorkaround.addItems(user.getBase().getInventory(), itemList.toArray(new ItemStack[0]));
|
||||
|
||||
final KitPreExpandItemsEvent itemsEvent = new KitPreExpandItemsEvent(user, kitName, itemList);
|
||||
Bukkit.getPluginManager().callEvent(itemsEvent);
|
||||
|
||||
final ItemStack[] itemArray = itemList.toArray(new ItemStack[0]);
|
||||
|
||||
if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, itemArray)) {
|
||||
user.sendMessage(tl("kitInvFullNoDrop"));
|
||||
return false;
|
||||
}
|
||||
|
||||
final Map<Integer, ItemStack> leftover = Inventories.addItem(user.getBase(), maxStackSize, autoEquip, itemArray);
|
||||
if (!isDropItemsIfFull && !leftover.isEmpty()) {
|
||||
// Inventories#hasSpace should prevent this state from EVER being reached; If it does, something has gone terribly wrong, and we should just give up and hope people report it :(
|
||||
throw new IllegalStateException("Something has gone terribly wrong while adding items to the user's inventory. Please report this to the EssentialsX developers. Items left over: " + leftover + ". Original items: " + Arrays.toString(itemArray));
|
||||
}
|
||||
|
||||
for (final ItemStack itemStack : leftover.values()) {
|
||||
int spillAmount = itemStack.getAmount();
|
||||
if (maxStackSize != 0) {
|
||||
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
|
||||
}
|
||||
for (final ItemStack itemStack : overfilled.values()) {
|
||||
int spillAmount = itemStack.getAmount();
|
||||
if (!allowOversizedStacks) {
|
||||
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
|
||||
}
|
||||
while (spillAmount > 0) {
|
||||
user.getWorld().dropItemNaturally(user.getLocation(), itemStack);
|
||||
spillAmount -= itemStack.getAmount();
|
||||
}
|
||||
spew = true;
|
||||
}
|
||||
} else {
|
||||
if (allowOversizedStacks) {
|
||||
overfilled = InventoryWorkaround.addAllOversizedItems(user.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), itemList.toArray(new ItemStack[0]));
|
||||
} else {
|
||||
overfilled = InventoryWorkaround.addAllItems(user.getBase().getInventory(), itemList.toArray(new ItemStack[0]));
|
||||
}
|
||||
if (overfilled != null) {
|
||||
user.sendMessage(tl("kitInvFullNoDrop"));
|
||||
return false;
|
||||
while (spillAmount > 0) {
|
||||
user.getWorld().dropItemNaturally(user.getLocation(), itemStack);
|
||||
spillAmount -= itemStack.getAmount();
|
||||
}
|
||||
spew = true;
|
||||
}
|
||||
user.getBase().updateInventory();
|
||||
|
||||
@@ -291,8 +272,4 @@ public class Kit {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isEmptyStack(ItemStack stack) {
|
||||
return stack == null || MaterialUtil.isAir(stack.getType());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IUser;
|
||||
import net.essentialsx.api.v2.services.mail.MailService;
|
||||
import net.essentialsx.api.v2.events.UserMailEvent;
|
||||
import net.essentialsx.api.v2.services.mail.MailMessage;
|
||||
import net.essentialsx.api.v2.services.mail.MailSender;
|
||||
import net.essentialsx.api.v2.services.mail.MailService;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -35,6 +37,12 @@ public class MailServiceImpl implements MailService {
|
||||
}
|
||||
|
||||
private void sendMail(IUser recipient, MailMessage message) {
|
||||
final UserMailEvent event = new UserMailEvent(recipient, message);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ArrayList<MailMessage> messages = recipient.getMailMessages();
|
||||
messages.add(0, message);
|
||||
recipient.setMailList(messages);
|
||||
|
||||
@@ -194,14 +194,14 @@ public class MetaItemStack {
|
||||
final Material WRITTEN_BOOK = EnumUtil.getMaterial("WRITTEN_BOOK");
|
||||
|
||||
if (split.length > 1 && split[0].equalsIgnoreCase("name") && hasMetaPermission(sender, "name", false, true, ess)) {
|
||||
final String displayName = FormatUtil.replaceFormat(split[1].replace('_', ' '));
|
||||
final String displayName = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
|
||||
final ItemMeta meta = stack.getItemMeta();
|
||||
meta.setDisplayName(displayName);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && (split[0].equalsIgnoreCase("lore") || split[0].equalsIgnoreCase("desc")) && hasMetaPermission(sender, "lore", false, true, ess)) {
|
||||
final List<String> lore = new ArrayList<>();
|
||||
for (final String line : split[1].split("(?<!\\\\)\\|")) {
|
||||
lore.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
|
||||
lore.add(FormatUtil.replaceFormat(line.replaceAll("(?<!\\\\)_", " ").replace("\\_", "_").replace("\\|", "|")));
|
||||
}
|
||||
final ItemMeta meta = stack.getItemMeta();
|
||||
meta.setLore(lore);
|
||||
@@ -230,7 +230,7 @@ public class MetaItemStack {
|
||||
meta.setAuthor(author);
|
||||
stack.setItemMeta(meta);
|
||||
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
|
||||
final String title = FormatUtil.replaceFormat(split[1].replace('_', ' '));
|
||||
final String title = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
|
||||
final BookMeta meta = (BookMeta) stack.getItemMeta();
|
||||
meta.setTitle(title);
|
||||
stack.setItemMeta(meta);
|
||||
@@ -240,7 +240,7 @@ public class MetaItemStack {
|
||||
final List<String> pages = meta.hasPages() ? new ArrayList<>(meta.getPages()) : new ArrayList<>();
|
||||
final List<String> lines = new ArrayList<>();
|
||||
for (final String line : split[1].split("(?<!\\\\)\\|")) {
|
||||
lines.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
|
||||
lines.add(FormatUtil.replaceFormat(line.replaceAll("(?<!\\\\)_", " ").replace("\\_", "_").replace("\\|", "|")));
|
||||
}
|
||||
final String content = String.join("\n", lines);
|
||||
if (page >= pages.size()) {
|
||||
|
||||
@@ -109,6 +109,8 @@ public enum Mob {
|
||||
TADPOLE("Tadpole", Enemies.FRIENDLY, "TADPOLE"),
|
||||
WARDEN("Warden", Enemies.ENEMY, "WARDEN"),
|
||||
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
|
||||
CAMEL("Camel", Enemies.FRIENDLY, "CAMEL"),
|
||||
SNIFFER("Sniffer", Enemies.FRIENDLY, "SNIFFER"),
|
||||
;
|
||||
|
||||
private static final Map<String, Mob> hashMap = new HashMap<>();
|
||||
|
||||
@@ -3,9 +3,11 @@ package com.earth2me.essentials;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.nms.refl.ReflUtil;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeSpecies;
|
||||
import org.bukkit.entity.Axolotl;
|
||||
import org.bukkit.entity.Boat;
|
||||
import org.bukkit.entity.Camel;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Fox;
|
||||
@@ -15,8 +17,10 @@ import org.bukkit.entity.MushroomCow;
|
||||
import org.bukkit.entity.Ocelot;
|
||||
import org.bukkit.entity.Panda;
|
||||
import org.bukkit.entity.Parrot;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TropicalFish;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -41,6 +45,7 @@ public final class MobCompat {
|
||||
public static final EntityType AXOLOTL = getEntityType("AXOLOTL");
|
||||
public static final EntityType GOAT = getEntityType("GOAT");
|
||||
public static final EntityType FROG = getEntityType("FROG");
|
||||
public static final EntityType CAMEL = getEntityType("CAMEL");
|
||||
|
||||
// Constants for mobs that have changed since earlier versions
|
||||
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
|
||||
@@ -195,6 +200,19 @@ public final class MobCompat {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCamelSaddle(final Entity entity, final Player target) {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_20_1_R01)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity instanceof Camel) {
|
||||
final Camel camel = (Camel) entity;
|
||||
camel.setTamed(true);
|
||||
camel.setOwner(target);
|
||||
camel.getInventory().setSaddle(new ItemStack(Material.SADDLE, 1));
|
||||
}
|
||||
}
|
||||
|
||||
public enum CatType {
|
||||
// These are (loosely) Mojang names for the cats
|
||||
SIAMESE("SIAMESE", "SIAMESE_CAT"),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -209,6 +209,7 @@ public enum MobData {
|
||||
MANGROVE_BOAT("mangrove", Boat.class, MobCompat.BoatVariant.MANGROVE, true),
|
||||
OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true),
|
||||
SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true),
|
||||
SADDLE_CAMEL("saddle", MobCompat.CAMEL, Data.CAMELSADDLE, true),
|
||||
;
|
||||
|
||||
final private String nickname;
|
||||
@@ -362,8 +363,8 @@ public enum MobData {
|
||||
((Horse) spawned).getInventory().setArmor(new ItemStack((Material) this.value, 1));
|
||||
} else if (this.type.equals(EntityType.ZOMBIE.getEntityClass()) || this.type.equals(EntityType.SKELETON)) {
|
||||
final EntityEquipment invent = ((LivingEntity) spawned).getEquipment();
|
||||
InventoryWorkaround.setItemInMainHand(invent, new ItemStack((Material) this.value, 1));
|
||||
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
|
||||
Inventories.setItemInMainHand(invent, new ItemStack((Material) this.value, 1));
|
||||
Inventories.setItemInMainHandDropChance(invent, 0.1f);
|
||||
}
|
||||
} else if (this.value.equals(Data.RAID_LEADER)) {
|
||||
((Raider) spawned).setPatrolLeader(true);
|
||||
@@ -387,6 +388,8 @@ public enum MobData {
|
||||
}
|
||||
} else if (this.value.equals(Data.GOAT_SCREAMING)) {
|
||||
((Goat) spawned).setScreaming(true);
|
||||
} else if (this.value.equals(Data.CAMELSADDLE)) {
|
||||
MobCompat.setCamelSaddle(spawned, target);
|
||||
} else if (this.value instanceof MobCompat.BoatVariant) {
|
||||
MobCompat.setBoatVariant(spawned, (MobCompat.BoatVariant) this.value);
|
||||
} else if (this.value instanceof String) {
|
||||
@@ -446,5 +449,6 @@ public enum MobData {
|
||||
FISH_BODY_COLOR,
|
||||
FISH_PATTERN_COLOR,
|
||||
GOAT_SCREAMING,
|
||||
CAMELSADDLE,
|
||||
}
|
||||
}
|
||||
@@ -55,9 +55,9 @@ public final class PlayerList {
|
||||
int playerHidden = 0;
|
||||
int hiddenCount = 0;
|
||||
for (final User onlinePlayer : ess.getOnlineUsers()) {
|
||||
if (onlinePlayer.isHidden() || (user != null && !user.getBase().canSee(onlinePlayer.getBase()))) {
|
||||
if (onlinePlayer.isHidden() || (user != null && onlinePlayer.isHiddenFrom(user.getBase()))) {
|
||||
playerHidden++;
|
||||
if (showHidden || user != null && user.getBase().canSee(onlinePlayer.getBase())) {
|
||||
if (showHidden || user != null && !onlinePlayer.isHiddenFrom(user.getBase())) {
|
||||
hiddenCount++;
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public final class PlayerList {
|
||||
public static Map<String, List<User>> getPlayerLists(final IEssentials ess, final IUser sender, final boolean showHidden) {
|
||||
final Map<String, List<User>> playerList = new HashMap<>();
|
||||
for (final User onlineUser : ess.getOnlineUsers()) {
|
||||
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && !sender.getBase().canSee(onlineUser.getBase()))) {
|
||||
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && onlineUser.isHiddenFrom(sender.getBase()))) {
|
||||
continue;
|
||||
}
|
||||
final String group = FormatUtil.stripFormat(FormatUtil.stripEssentialsFormat(onlineUser.getGroup().toLowerCase()));
|
||||
|
||||
@@ -4,15 +4,17 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerTarget implements ITarget {
|
||||
private final String name;
|
||||
private final UUID uuid;
|
||||
|
||||
public PlayerTarget(final Player entity) {
|
||||
this.name = entity.getName();
|
||||
this.uuid = entity.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return Bukkit.getServer().getPlayerExact(name).getLocation();
|
||||
return Bukkit.getPlayer(uuid).getLocation();
|
||||
}
|
||||
}
|
||||
@@ -1469,10 +1469,16 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
// #easteregg
|
||||
@Override
|
||||
public int getMaxUserCacheCount() {
|
||||
final long count = Runtime.getRuntime().maxMemory() / 1024 / 96;
|
||||
final long count = Runtime.getRuntime().maxMemory() / 1024 / 1024;
|
||||
return config.getInt("max-user-cache-count", (int) count);
|
||||
}
|
||||
|
||||
// #easteregg
|
||||
@Override
|
||||
public long getMaxUserCacheValueExpiry() {
|
||||
return config.getLong("max-user-cache-value-expiry", 600);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLastMessageReplyRecipient() {
|
||||
return config.getBoolean("last-message-reply-recipient", false);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.Mob.MobException;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
@@ -251,8 +251,8 @@ public final class SpawnMob {
|
||||
private static void defaultMobData(final EntityType type, final Entity spawned) {
|
||||
if (type == EntityType.SKELETON) {
|
||||
final EntityEquipment invent = ((LivingEntity) spawned).getEquipment();
|
||||
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(Material.BOW, 1));
|
||||
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
|
||||
Inventories.setItemInMainHand(invent, new ItemStack(Material.BOW, 1));
|
||||
Inventories.setItemInMainHandDropChance(invent, 0.1f);
|
||||
}
|
||||
|
||||
if (type == MobCompat.ZOMBIFIED_PIGLIN) {
|
||||
@@ -260,8 +260,8 @@ public final class SpawnMob {
|
||||
setVillager(zombie, false);
|
||||
|
||||
final EntityEquipment invent = zombie.getEquipment();
|
||||
InventoryWorkaround.setItemInMainHand(invent, new ItemStack(GOLDEN_SWORD, 1));
|
||||
InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f);
|
||||
Inventories.setItemInMainHand(invent, new ItemStack(GOLDEN_SWORD, 1));
|
||||
Inventories.setItemInMainHandDropChance(invent, 0.1f);
|
||||
}
|
||||
|
||||
if (type == EntityType.ZOMBIE) {
|
||||
|
||||
@@ -1,51 +1,22 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import com.earth2me.essentials.commands.Commandnuke;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
|
||||
public class TNTExplodeListener implements Listener, Runnable {
|
||||
private final transient IEssentials ess;
|
||||
private transient boolean enabled = false;
|
||||
private transient int timer = -1;
|
||||
|
||||
public TNTExplodeListener(final IEssentials ess) {
|
||||
super();
|
||||
this.ess = ess;
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
if (!enabled) {
|
||||
enabled = true;
|
||||
timer = ess.scheduleSyncDelayedTask(this, 200);
|
||||
return;
|
||||
}
|
||||
if (timer != -1) {
|
||||
ess.getScheduler().cancelTask(timer);
|
||||
timer = ess.scheduleSyncDelayedTask(this, 200);
|
||||
}
|
||||
}
|
||||
|
||||
public class TNTExplodeListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onEntityExplode(final EntityExplodeEvent event) {
|
||||
if (!enabled) {
|
||||
if (!(event.getEntity() instanceof TNTPrimed)) {
|
||||
return;
|
||||
}
|
||||
if (event.getEntity() instanceof LivingEntity) {
|
||||
return;
|
||||
}
|
||||
if (event.blockList().size() < 1) {
|
||||
if (!event.getEntity().hasMetadata(Commandnuke.NUKE_META_KEY)) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
event.getLocation().getWorld().createExplosion(event.getLocation(), 0F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.craftbukkit.SetExpFix;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -8,7 +8,6 @@ import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
@@ -16,6 +15,7 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -197,7 +197,7 @@ public class Trade {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getItemStack() != null && !user.getBase().getInventory().containsAtLeast(itemStack, itemStack.getAmount())) {
|
||||
if (getItemStack() != null && !Inventories.containsAtLeast(user.getBase(), itemStack, itemStack.getAmount())) {
|
||||
future.completeExceptionally(new ChargeException(tl("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack()))));
|
||||
return;
|
||||
}
|
||||
@@ -225,52 +225,33 @@ public class Trade {
|
||||
user.giveMoney(getMoney());
|
||||
}
|
||||
if (getItemStack() != null) {
|
||||
// This stores the would be overflow
|
||||
final Map<Integer, ItemStack> overFlow = InventoryWorkaround.addAllItems(user.getBase().getInventory(), getItemStack());
|
||||
if (type == OverflowType.ABORT && !Inventories.hasSpace(user.getBase(), 0, false, getItemStack())) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "abort paying " + user.getName() + " itemstack " + getItemStack().toString() + " due to lack of inventory space ");
|
||||
}
|
||||
return Collections.singletonMap(0, getItemStack());
|
||||
}
|
||||
|
||||
if (overFlow != null) {
|
||||
switch (type) {
|
||||
case ABORT:
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "abort paying " + user.getName() + " itemstack " + getItemStack().toString() + " due to lack of inventory space ");
|
||||
final Map<Integer, ItemStack> leftover = Inventories.addItem(user.getBase(), getItemStack());
|
||||
user.getBase().updateInventory();
|
||||
if (!leftover.isEmpty()) {
|
||||
if (type == OverflowType.RETURN) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " with overflow " + leftover.get(0).toString());
|
||||
}
|
||||
return leftover;
|
||||
} else {
|
||||
for (final ItemStack itemStack : leftover.values()) {
|
||||
int spillAmount = itemStack.getAmount();
|
||||
itemStack.setAmount(Math.min(spillAmount, itemStack.getMaxStackSize()));
|
||||
while (spillAmount > 0) {
|
||||
user.getBase().getWorld().dropItemNaturally(user.getBase().getLocation(), itemStack);
|
||||
spillAmount -= itemStack.getAmount();
|
||||
}
|
||||
|
||||
return overFlow;
|
||||
|
||||
case RETURN:
|
||||
// Pay the user the items, and return overflow
|
||||
final Map<Integer, ItemStack> returnStack = InventoryWorkaround.addItems(user.getBase().getInventory(), getItemStack());
|
||||
user.getBase().updateInventory();
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " with overflow " + returnStack.get(0).toString());
|
||||
}
|
||||
|
||||
return returnStack;
|
||||
case DROP:
|
||||
// Pay the users the items directly, and drop the rest, will always return no overflow.
|
||||
final Map<Integer, ItemStack> leftOver = InventoryWorkaround.addItems(user.getBase().getInventory(), getItemStack());
|
||||
final Location loc = user.getBase().getLocation();
|
||||
for (final ItemStack loStack : leftOver.values()) {
|
||||
final int maxStackSize = loStack.getType().getMaxStackSize();
|
||||
final int stacks = loStack.getAmount() / maxStackSize;
|
||||
final int leftover = loStack.getAmount() % maxStackSize;
|
||||
final Item[] itemStacks = new Item[stacks + (leftover > 0 ? 1 : 0)];
|
||||
for (int i = 0; i < stacks; i++) {
|
||||
final ItemStack stack = loStack.clone();
|
||||
stack.setAmount(maxStackSize);
|
||||
itemStacks[i] = loc.getWorld().dropItem(loc, stack);
|
||||
}
|
||||
if (leftover > 0) {
|
||||
final ItemStack stack = loStack.clone();
|
||||
stack.setAmount(leftover);
|
||||
itemStacks[stacks] = loc.getWorld().dropItem(loc, stack);
|
||||
}
|
||||
}
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " and dropping overflow " + leftOver.get(0).toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " partial itemstack " + getItemStack().toString() + " and dropping overflow " + leftover.get(0).toString());
|
||||
}
|
||||
}
|
||||
} else if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "paying " + user.getName() + " itemstack " + getItemStack().toString());
|
||||
@@ -315,11 +296,11 @@ public class Trade {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString());
|
||||
}
|
||||
if (!user.getBase().getInventory().containsAtLeast(getItemStack(), getItemStack().getAmount())) {
|
||||
if (!Inventories.containsAtLeast(user.getBase(), getItemStack(), getItemStack().getAmount())) {
|
||||
future.completeExceptionally(new ChargeException(tl("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " "))));
|
||||
return;
|
||||
}
|
||||
user.getBase().getInventory().removeItem(getItemStack());
|
||||
Inventories.removeItemAmount(user.getBase(), getItemStack(), getItemStack().getAmount());
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
if (command != null) {
|
||||
|
||||
@@ -1,155 +1,19 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Deprecated
|
||||
public class UUIDMap {
|
||||
private static final ScheduledExecutorService writeScheduler = Executors.newScheduledThreadPool(1);
|
||||
private static boolean pendingWrite;
|
||||
private static boolean loading = false;
|
||||
private final transient net.ess3.api.IEssentials ess;
|
||||
private final File userList;
|
||||
private final transient Pattern splitPattern = Pattern.compile(",");
|
||||
private final Runnable writeTaskRunnable;
|
||||
|
||||
public UUIDMap(final net.ess3.api.IEssentials ess) {
|
||||
this.ess = ess;
|
||||
userList = new File(ess.getDataFolder(), "usermap.csv");
|
||||
pendingWrite = false;
|
||||
writeTaskRunnable = () -> {
|
||||
if (pendingWrite) {
|
||||
try {
|
||||
new WriteRunner(ess.getDataFolder(), userList, ess.getUserMap().getNames()).run();
|
||||
} catch (final Throwable t) { // bad code to prevent task from being suppressed
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
writeScheduler.scheduleWithFixedDelay(writeTaskRunnable, 5, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void loadAllUsers(final ConcurrentSkipListMap<String, UUID> names, final ConcurrentSkipListMap<UUID, ArrayList<String>> history) {
|
||||
try {
|
||||
if (!userList.exists()) {
|
||||
userList.createNewFile();
|
||||
}
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Reading usermap from disk");
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
names.clear();
|
||||
history.clear();
|
||||
loading = true;
|
||||
|
||||
try (final BufferedReader reader = new BufferedReader(new FileReader(userList))) {
|
||||
while (true) {
|
||||
final String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
} else {
|
||||
final String[] values = splitPattern.split(line);
|
||||
if (values.length == 2) {
|
||||
final String name = values[0];
|
||||
final UUID uuid = UUID.fromString(values[1]);
|
||||
names.put(name, uuid);
|
||||
if (!history.containsKey(uuid)) {
|
||||
final ArrayList<String> list = new ArrayList<>();
|
||||
list.add(name);
|
||||
history.put(uuid, list);
|
||||
} else {
|
||||
final ArrayList<String> list = history.get(uuid);
|
||||
if (!list.contains(name)) {
|
||||
list.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loading = false;
|
||||
} catch (final IOException ex) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
public UUIDMap() {
|
||||
}
|
||||
|
||||
public void writeUUIDMap() {
|
||||
pendingWrite = true;
|
||||
//no-op
|
||||
}
|
||||
|
||||
public void forceWriteUUIDMap() {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Forcing usermap write to disk");
|
||||
}
|
||||
pendingWrite = true;
|
||||
writeTaskRunnable.run();
|
||||
//no-op
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
writeScheduler.submit(writeTaskRunnable);
|
||||
writeScheduler.shutdown();
|
||||
}
|
||||
|
||||
private static final class WriteRunner implements Runnable {
|
||||
private final File location;
|
||||
private final File endFile;
|
||||
private final Map<String, UUID> names;
|
||||
|
||||
private WriteRunner(final File location, final File endFile, final Map<String, UUID> names) {
|
||||
this.location = location;
|
||||
this.endFile = endFile;
|
||||
this.names = new HashMap<>(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
pendingWrite = false;
|
||||
if (loading || names.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
File configFile = null;
|
||||
|
||||
try {
|
||||
configFile = File.createTempFile("usermap", ".tmp.csv", location);
|
||||
|
||||
final BufferedWriter bWriter = new BufferedWriter(new FileWriter(configFile));
|
||||
for (final Map.Entry<String, UUID> entry : names.entrySet()) {
|
||||
bWriter.write(entry.getKey() + "," + entry.getValue().toString());
|
||||
bWriter.newLine();
|
||||
}
|
||||
|
||||
bWriter.close();
|
||||
Files.move(configFile, endFile);
|
||||
} catch (final IOException ex) {
|
||||
try {
|
||||
if (configFile != null && configFile.exists()) {
|
||||
Files.move(configFile, new File(endFile.getParentFile(), "usermap.bak.csv"));
|
||||
}
|
||||
} catch (final Exception ex2) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, ex2.getMessage(), ex2);
|
||||
}
|
||||
Essentials.getWrappedLogger().log(Level.WARNING, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
//no-op
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.economy.EconomyLayer;
|
||||
import com.earth2me.essentials.economy.EconomyLayers;
|
||||
import com.earth2me.essentials.messaging.IMessageRecipient;
|
||||
@@ -27,7 +28,6 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
@@ -90,6 +90,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
private String lastHomeConfirmation;
|
||||
private long lastHomeConfirmationTimestamp;
|
||||
private Boolean toggleShout;
|
||||
private boolean freeze = false;
|
||||
private transient final List<String> signCopy = Lists.newArrayList("", "", "", "");
|
||||
private transient long lastVanishTime = System.currentTimeMillis();
|
||||
|
||||
@@ -106,7 +107,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
this.messageRecipient = new SimpleMessageRecipient(ess, this);
|
||||
}
|
||||
|
||||
void update(final Player base) {
|
||||
public void update(final Player base) {
|
||||
setBase(base);
|
||||
}
|
||||
|
||||
@@ -151,7 +152,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
private boolean isAuthorizedCheck(final String node) {
|
||||
if (base instanceof OfflinePlayer) {
|
||||
if (base instanceof OfflinePlayerStub) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
private boolean isPermSetCheck(final String node) {
|
||||
if (base instanceof OfflinePlayer) {
|
||||
if (base instanceof OfflinePlayerStub) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -187,7 +188,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
private TriState isAuthorizedExactCheck(final String node) {
|
||||
if (base instanceof OfflinePlayer) {
|
||||
if (base instanceof OfflinePlayerStub) {
|
||||
return TriState.UNSET;
|
||||
}
|
||||
|
||||
@@ -310,7 +311,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
|
||||
private void _dispose() {
|
||||
if (!base.isOnline()) {
|
||||
this.base = new OfflinePlayer(getConfigUUID(), ess.getServer());
|
||||
this.base = new OfflinePlayerStub(getConfigUUID(), ess.getServer());
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
@@ -464,7 +465,11 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
} else if (nick.equalsIgnoreCase(getName())) {
|
||||
nickname = nick;
|
||||
} else {
|
||||
nickname = FormatUtil.replaceFormat(ess.getSettings().getNicknamePrefix()) + nick;
|
||||
if (isAuthorized("essentials.nick.hideprefix")) {
|
||||
nickname = nick;
|
||||
} else {
|
||||
nickname = FormatUtil.replaceFormat(ess.getSettings().getNicknamePrefix()) + nick;
|
||||
}
|
||||
suffix = "§r";
|
||||
}
|
||||
|
||||
@@ -674,6 +679,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
|
||||
@Override
|
||||
public boolean isHiddenFrom(Player player) {
|
||||
if (getBase() instanceof OfflinePlayerStub || player instanceof OfflinePlayerStub) {
|
||||
return true;
|
||||
}
|
||||
return !player.canSee(getBase());
|
||||
}
|
||||
|
||||
@@ -701,7 +709,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
public boolean isHidden(final Player player) {
|
||||
return hidden || !player.canSee(getBase());
|
||||
return hidden || isHiddenFrom(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1137,12 +1145,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
* Returns the {@link ItemStack} in the main hand or off-hand. If the main hand is empty then the offhand item is returned - also nullable.
|
||||
*/
|
||||
public ItemStack getItemInHand() {
|
||||
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_9_R01)) {
|
||||
return getBase().getInventory().getItemInHand();
|
||||
} else {
|
||||
final PlayerInventory inventory = getBase().getInventory();
|
||||
return inventory.getItemInMainHand() != null ? inventory.getItemInMainHand() : inventory.getItemInOffHand();
|
||||
}
|
||||
return Inventories.getItemInHand(getBase());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1192,6 +1195,16 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return signCopy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFreeze() {
|
||||
return freeze;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFreeze(boolean freeze) {
|
||||
this.freeze = freeze;
|
||||
}
|
||||
|
||||
public boolean isBaltopExempt() {
|
||||
if (getBase().isOnline()) {
|
||||
final boolean exempt = isAuthorized("essentials.balancetop.exclude");
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.earth2me.essentials.config.EssentialsUserConfiguration;
|
||||
import com.earth2me.essentials.config.entities.CommandCooldown;
|
||||
import com.earth2me.essentials.config.entities.LazyLocation;
|
||||
import com.earth2me.essentials.config.holders.UserConfigHolder;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
@@ -16,7 +17,6 @@ import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
@@ -43,19 +43,14 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
super(base);
|
||||
this.ess = ess;
|
||||
final File folder = new File(ess.getDataFolder(), "userdata");
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs();
|
||||
if (!folder.exists() && !folder.mkdirs()) {
|
||||
throw new RuntimeException("Unable to create userdata folder!");
|
||||
}
|
||||
|
||||
String filename;
|
||||
try {
|
||||
filename = base.getUniqueId().toString();
|
||||
} catch (final Throwable ex) {
|
||||
ess.getLogger().warning("Falling back to old username system for " + base.getName());
|
||||
filename = base.getName();
|
||||
}
|
||||
|
||||
config = new EssentialsUserConfiguration(base.getName(), base.getUniqueId(), new File(folder, filename + ".yml"));
|
||||
config = new EssentialsUserConfiguration(base.getName(), base.getUniqueId(), new File(folder, base.getUniqueId() + ".yml"));
|
||||
config.setSaveHook(() -> {
|
||||
config.setRootHolder(UserConfigHolder.class, holder);
|
||||
});
|
||||
reloadConfig();
|
||||
|
||||
if (config.getUsername() == null) {
|
||||
@@ -65,12 +60,15 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
|
||||
public final void reset() {
|
||||
config.blockingSave();
|
||||
config.getFile().delete();
|
||||
if (!config.getFile().delete()) {
|
||||
ess.getLogger().warning("Unable to delete data file for " + config.getFile().getName());
|
||||
}
|
||||
if (config.getUsername() != null) {
|
||||
ess.getUserMap().removeUser(config.getUsername());
|
||||
final ModernUserMap users = (ModernUserMap) ess.getUsers();
|
||||
users.invalidate(config.getUuid());
|
||||
if (isNPC()) {
|
||||
final String uuid = UUID.nameUUIDFromBytes(("NPC:" + StringUtil.safeString(config.getUsername())).getBytes(Charsets.UTF_8)).toString();
|
||||
ess.getUserMap().removeUserUUID(uuid);
|
||||
final String name = ess.getSettings().isSafeUsermap() ? StringUtil.safeString(config.getUsername()) : config.getUsername();
|
||||
users.invalidate(UUID.nameUUIDFromBytes(("NPC:" + name).getBytes(Charsets.UTF_8)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,18 +82,10 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
config.load();
|
||||
try {
|
||||
holder = config.getRootNode().get(UserConfigHolder.class);
|
||||
} catch (SerializationException e) {
|
||||
} catch (Throwable e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while reading user config: " + config.getFile().getName(), e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
config.setSaveHook(() -> {
|
||||
try {
|
||||
config.getRootNode().set(UserConfigHolder.class, holder);
|
||||
} catch (SerializationException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while saving user config: " + config.getFile().getName(), e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
money = _getMoney();
|
||||
}
|
||||
|
||||
@@ -208,6 +198,16 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
}
|
||||
}
|
||||
|
||||
public void renameHome(final String name, final String newName) throws Exception {
|
||||
final LazyLocation location = holder.homes().remove(name);
|
||||
if (location != null) {
|
||||
holder.homes().put(StringUtil.safeString(newName), location);
|
||||
config.save();
|
||||
} else {
|
||||
throw new Exception(tl("invalidHome", name));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasHome() {
|
||||
return !holder.homes().isEmpty();
|
||||
}
|
||||
@@ -589,9 +589,13 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
}
|
||||
|
||||
public void setLastAccountName(final String lastAccountName) {
|
||||
if (getLastAccountName() != null && !getLastAccountName().equals(lastAccountName)) {
|
||||
final List<String> usernames = holder.pastUsernames();
|
||||
usernames.add(0, getLastAccountName());
|
||||
holder.pastUsernames(usernames);
|
||||
}
|
||||
holder.lastAccountName(lastAccountName);
|
||||
config.save();
|
||||
ess.getUserMap().trackUUID(getConfigUUID(), lastAccountName, true);
|
||||
}
|
||||
|
||||
public boolean arePowerToolsEnabled() {
|
||||
@@ -722,6 +726,17 @@ public abstract class UserData extends PlayerExtension implements IConf {
|
||||
config.save();
|
||||
}
|
||||
|
||||
public List<String> getPastUsernames() {
|
||||
return holder.pastUsernames();
|
||||
}
|
||||
|
||||
public void addPastUsername(String username) {
|
||||
final List<String> usernames = holder.pastUsernames();
|
||||
usernames.add(0, username);
|
||||
holder.pastUsernames(usernames);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public boolean isShouting() {
|
||||
if (holder.shouting() == null) {
|
||||
holder.shouting(ess.getSettings().isShoutDefault());
|
||||
|
||||
@@ -1,383 +1,70 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.UserDoesNotExistException;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class UserMap extends CacheLoader<String, User> implements IConf {
|
||||
private static boolean legacy = false;
|
||||
private static Method getLegacy;
|
||||
private final transient IEssentials ess;
|
||||
private final transient ConcurrentSkipListSet<UUID> keys = new ConcurrentSkipListSet<>();
|
||||
private final transient ConcurrentSkipListMap<String, UUID> names = new ConcurrentSkipListMap<>();
|
||||
private final transient ConcurrentSkipListMap<UUID, ArrayList<String>> history = new ConcurrentSkipListMap<>();
|
||||
private final UUIDMap uuidMap;
|
||||
private final transient Cache<String, User> users;
|
||||
private final Pattern validUserPattern = Pattern.compile("^[a-zA-Z0-9_]{2,16}$");
|
||||
@Deprecated
|
||||
public class UserMap {
|
||||
private final transient ModernUserMap userMap;
|
||||
private final transient UUIDMap uuidMap;
|
||||
|
||||
private static final String WARN_UUID_NOT_REPLACE = "Found UUID {0} for player {1}, but player already has a UUID ({2}). Not replacing UUID in usermap.";
|
||||
|
||||
public UserMap(final IEssentials ess) {
|
||||
super();
|
||||
this.ess = ess;
|
||||
uuidMap = new UUIDMap(ess);
|
||||
//RemovalListener<UUID, User> remListener = new UserMapRemovalListener();
|
||||
//users = CacheBuilder.newBuilder().maximumSize(ess.getSettings().getMaxUserCacheCount()).softValues().removalListener(remListener).build(this);
|
||||
final CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder();
|
||||
final int maxCount = ess.getSettings().getMaxUserCacheCount();
|
||||
try {
|
||||
cacheBuilder.maximumSize(maxCount);
|
||||
} catch (final NoSuchMethodError nsme) {
|
||||
legacy = true;
|
||||
legacyMaximumSize(cacheBuilder, maxCount);
|
||||
}
|
||||
cacheBuilder.softValues();
|
||||
if (!legacy) {
|
||||
users = cacheBuilder.build(this);
|
||||
} else {
|
||||
users = legacyBuild(cacheBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAllUsersAsync(final IEssentials ess) {
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
synchronized (users) {
|
||||
final File userdir = new File(ess.getDataFolder(), "userdata");
|
||||
if (!userdir.exists()) {
|
||||
return;
|
||||
}
|
||||
keys.clear();
|
||||
users.invalidateAll();
|
||||
for (final String string : userdir.list()) {
|
||||
if (!string.endsWith(".yml")) {
|
||||
continue;
|
||||
}
|
||||
final String name = string.substring(0, string.length() - 4);
|
||||
try {
|
||||
keys.add(UUID.fromString(name));
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
//Ignore these users till they rejoin.
|
||||
}
|
||||
}
|
||||
uuidMap.loadAllUsers(names, history);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean userExists(final UUID uuid) {
|
||||
return keys.contains(uuid);
|
||||
public UserMap(final ModernUserMap userMap) {
|
||||
this.userMap = userMap;
|
||||
this.uuidMap = new UUIDMap();
|
||||
}
|
||||
|
||||
public User getUser(final String name) {
|
||||
final String sanitizedName = StringUtil.safeString(name);
|
||||
try {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().warning("Looking up username " + name + " (" + sanitizedName + ") ...");
|
||||
}
|
||||
|
||||
if (names.containsKey(sanitizedName)) {
|
||||
final UUID uuid = names.get(sanitizedName);
|
||||
return getUser(uuid);
|
||||
}
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().warning(name + "(" + sanitizedName + ") has no known usermap entry");
|
||||
}
|
||||
|
||||
final File userFile = getUserFileFromString(sanitizedName);
|
||||
if (userFile.exists()) {
|
||||
ess.getLogger().info("Importing user " + name + " to usermap.");
|
||||
final User user = new User(new OfflinePlayer(sanitizedName, ess.getServer()), ess);
|
||||
trackUUID(user.getBase().getUniqueId(), user.getName(), true);
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
} catch (final UncheckedExecutionException ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.WARNING, ex, () -> String.format("Exception while getting user for %s (%s)", name, sanitizedName));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return userMap.getUser(name);
|
||||
}
|
||||
|
||||
public User getUser(final UUID uuid) {
|
||||
try {
|
||||
if (!legacy) {
|
||||
return ((LoadingCache<String, User>) users).get(uuid.toString());
|
||||
} else {
|
||||
return legacyCacheGet(uuid);
|
||||
}
|
||||
} catch (final ExecutionException | UncheckedExecutionException ex) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.WARNING, ex, () -> "Exception while getting user for " + uuid);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return userMap.getUser(uuid);
|
||||
}
|
||||
|
||||
public void trackUUID(final UUID uuid, final String name, final boolean replace) {
|
||||
if (uuid != null) {
|
||||
keys.add(uuid);
|
||||
if (name != null && name.length() > 0) {
|
||||
final String keyName = ess.getSettings().isSafeUsermap() ? StringUtil.safeString(name) : name;
|
||||
if (!names.containsKey(keyName)) {
|
||||
names.put(keyName, uuid);
|
||||
uuidMap.writeUUIDMap();
|
||||
} else if (!isUUIDMatch(uuid, keyName)) {
|
||||
if (replace) {
|
||||
ess.getLogger().info("Found new UUID for " + name + ". Replacing " + names.get(keyName).toString() + " with " + uuid.toString());
|
||||
names.put(keyName, uuid);
|
||||
uuidMap.writeUUIDMap();
|
||||
} else {
|
||||
ess.getLogger().log(Level.INFO, MessageFormat.format(WARN_UUID_NOT_REPLACE, uuid.toString(), name, names.get(keyName).toString()), new RuntimeException());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// no-op
|
||||
}
|
||||
|
||||
public boolean isUUIDMatch(final UUID uuid, final String name) {
|
||||
return names.containsKey(name) && names.get(name).equals(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User load(final String stringUUID) throws Exception {
|
||||
final UUID uuid = UUID.fromString(stringUUID);
|
||||
Player player = ess.getServer().getPlayer(uuid);
|
||||
if (player != null) {
|
||||
final User user = new User(player, ess);
|
||||
trackUUID(uuid, user.getName(), true);
|
||||
return user;
|
||||
}
|
||||
|
||||
final File userFile = getUserFileFromID(uuid);
|
||||
|
||||
if (userFile.exists()) {
|
||||
player = new OfflinePlayer(uuid, ess.getServer());
|
||||
final User user = new User(player, ess);
|
||||
((OfflinePlayer) player).setName(user.getLastAccountName());
|
||||
trackUUID(uuid, user.getName(), false);
|
||||
return user;
|
||||
}
|
||||
|
||||
throw new Exception("User not found!");
|
||||
return userMap.load(UUID.fromString(stringUUID));
|
||||
}
|
||||
|
||||
public User load(final org.bukkit.OfflinePlayer player) throws UserDoesNotExistException {
|
||||
if (player == null) {
|
||||
throw new IllegalArgumentException("Player cannot be null!");
|
||||
}
|
||||
|
||||
final Player userPlayer;
|
||||
if (player instanceof Player) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Loading online OfflinePlayer into user map...");
|
||||
}
|
||||
final User user = new User((Player) player, ess);
|
||||
trackUUID(player.getUniqueId(), player.getName(), true);
|
||||
return user;
|
||||
}
|
||||
|
||||
final File userFile = getUserFileFromID(player.getUniqueId());
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Loading OfflinePlayer into user map. Has data: " + userFile.exists() + " for " + player);
|
||||
}
|
||||
|
||||
final OfflinePlayer essPlayer = new OfflinePlayer(player.getUniqueId(), ess.getServer());
|
||||
final User user = new User(essPlayer, ess);
|
||||
if (userFile.exists()) {
|
||||
essPlayer.setName(user.getLastAccountName());
|
||||
userPlayer = (Player) player;
|
||||
} else {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("OfflinePlayer usermap load saving user data for " + player);
|
||||
}
|
||||
|
||||
// this code makes me sad
|
||||
user.startTransaction();
|
||||
try {
|
||||
user.setMoney(ess.getSettings().getStartingBalance());
|
||||
} catch (MaxMoneyException e) {
|
||||
// Shouldn't happen as it would be an illegal configuration state
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
user.setLastAccountName(user.getName());
|
||||
user.stopTransaction();
|
||||
final OfflinePlayerStub essPlayer = new OfflinePlayerStub(player.getUniqueId(), Bukkit.getServer());
|
||||
essPlayer.setName(player.getName());
|
||||
userPlayer = essPlayer;
|
||||
}
|
||||
|
||||
trackUUID(player.getUniqueId(), user.getName(), false);
|
||||
final User user = userMap.getUser(userPlayer);
|
||||
if (user == null) {
|
||||
throw new UserDoesNotExistException("User not found");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
getUUIDMap().forceWriteUUIDMap();
|
||||
loadAllUsersAsync(ess);
|
||||
}
|
||||
|
||||
public void invalidateAll() {
|
||||
users.invalidateAll();
|
||||
}
|
||||
|
||||
public void removeUser(final String name) {
|
||||
if (names == null) {
|
||||
ess.getLogger().warning("Name collection is null, cannot remove user.");
|
||||
return;
|
||||
}
|
||||
final UUID uuid = names.get(name);
|
||||
if (uuid != null) {
|
||||
keys.remove(uuid);
|
||||
users.invalidate(uuid.toString());
|
||||
}
|
||||
names.remove(name);
|
||||
names.remove(StringUtil.safeString(name));
|
||||
}
|
||||
|
||||
public void removeUserUUID(final String uuid) {
|
||||
users.invalidate(uuid);
|
||||
}
|
||||
|
||||
public Set<UUID> getAllUniqueUsers() {
|
||||
return Collections.unmodifiableSet(keys);
|
||||
return userMap.getAllUserUUIDs();
|
||||
}
|
||||
|
||||
public int getUniqueUsers() {
|
||||
return keys.size();
|
||||
return userMap.getUserCount();
|
||||
}
|
||||
|
||||
protected ConcurrentSkipListMap<String, UUID> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
protected ConcurrentSkipListMap<UUID, ArrayList<String>> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public List<String> getUserHistory(final UUID uuid) {
|
||||
return history.get(uuid);
|
||||
return new ConcurrentSkipListMap<>(userMap.getNameCache());
|
||||
}
|
||||
|
||||
public UUIDMap getUUIDMap() {
|
||||
return uuidMap;
|
||||
}
|
||||
// class UserMapRemovalListener implements RemovalListener
|
||||
// {
|
||||
// @Override
|
||||
// public void onRemoval(final RemovalNotification notification)
|
||||
// {
|
||||
// Object value = notification.getValue();
|
||||
// if (value != null)
|
||||
// {
|
||||
// ((User)value).cleanup();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private File getUserFileFromID(final UUID uuid) {
|
||||
final File userFolder = new File(ess.getDataFolder(), "userdata");
|
||||
return new File(userFolder, uuid.toString() + ".yml");
|
||||
}
|
||||
|
||||
public File getUserFileFromString(final String name) {
|
||||
final File userFolder = new File(ess.getDataFolder(), "userdata");
|
||||
return new File(userFolder, StringUtil.sanitizeFileName(name) + ".yml");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public User getUserFromBukkit(String name) {
|
||||
name = StringUtil.safeString(name);
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().warning("Using potentially blocking Bukkit UUID lookup for: " + name);
|
||||
}
|
||||
// Don't attempt to look up entirely invalid usernames
|
||||
if (name == null || !validUserPattern.matcher(name).matches()) {
|
||||
return null;
|
||||
}
|
||||
final org.bukkit.OfflinePlayer offlinePlayer = ess.getServer().getOfflinePlayer(name);
|
||||
if (offlinePlayer == null) {
|
||||
return null;
|
||||
}
|
||||
final UUID uuid;
|
||||
try {
|
||||
uuid = offlinePlayer.getUniqueId();
|
||||
} catch (final UnsupportedOperationException | NullPointerException e) {
|
||||
return null;
|
||||
}
|
||||
// This is how Bukkit generates fake UUIDs
|
||||
if (UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)).equals(uuid)) {
|
||||
return null;
|
||||
} else {
|
||||
names.put(name, uuid);
|
||||
return getUser(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private User legacyCacheGet(final UUID uuid) {
|
||||
if (getLegacy == null) {
|
||||
final Class<?> usersClass = users.getClass();
|
||||
for (final Method m : usersClass.getDeclaredMethods()) {
|
||||
if (m.getName().equals("get")) {
|
||||
getLegacy = m;
|
||||
getLegacy.setAccessible(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (User) getLegacy.invoke(users, uuid.toString());
|
||||
} catch (final IllegalAccessException | InvocationTargetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void legacyMaximumSize(final CacheBuilder builder, final int maxCount) {
|
||||
try {
|
||||
final Method maxSizeLegacy = builder.getClass().getDeclaredMethod("maximumSize", Integer.TYPE);
|
||||
maxSizeLegacy.setAccessible(true);
|
||||
maxSizeLegacy.invoke(builder, maxCount);
|
||||
} catch (final NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Cache<String, User> legacyBuild(final CacheBuilder builder) {
|
||||
Method build = null;
|
||||
for (final Method method : builder.getClass().getDeclaredMethods()) {
|
||||
if (method.getName().equals("build")) {
|
||||
build = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Cache<String, User> legacyUsers;
|
||||
try {
|
||||
assert build != null;
|
||||
build.setAccessible(true);
|
||||
legacyUsers = (Cache<String, User>) build.invoke(builder, this);
|
||||
} catch (final IllegalAccessException | InvocationTargetException e) {
|
||||
legacyUsers = null;
|
||||
}
|
||||
return legacyUsers;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ public class Warps implements IConf, net.ess3.api.IWarps {
|
||||
public final void reloadConfig() {
|
||||
warpPoints.clear();
|
||||
final File[] listOfFiles = warpsFolder.listFiles();
|
||||
if (listOfFiles.length >= 1) {
|
||||
if (listOfFiles != null) {
|
||||
for (final File listOfFile : listOfFiles) {
|
||||
final String filename = listOfFile.getName();
|
||||
if (listOfFile.isFile() && filename.endsWith(".yml")) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.earth2me.essentials;
|
||||
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
|
||||
import com.earth2me.essentials.config.ConfigurateUtil;
|
||||
import com.earth2me.essentials.config.EssentialsConfiguration;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -101,7 +102,7 @@ public class Worth implements IConf {
|
||||
}
|
||||
|
||||
int max = 0;
|
||||
for (final ItemStack s : user.getBase().getInventory().getContents()) {
|
||||
for (final ItemStack s : Inventories.getInventory(user.getBase(), false)) {
|
||||
if (s == null || !s.isSimilar(is)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.earth2me.essentials.api;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.config.EssentialsUserConfiguration;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
@@ -41,9 +42,9 @@ public class Economy {
|
||||
ess = aEss;
|
||||
}
|
||||
|
||||
private static void createNPCFile(String name) {
|
||||
private static void createNPCFile(final String unsanitizedName) {
|
||||
final File folder = new File(ess.getDataFolder(), "userdata");
|
||||
name = StringUtil.safeString(name);
|
||||
final String name = ess.getSettings().isSafeUsermap() ? StringUtil.safeString(unsanitizedName) : unsanitizedName;
|
||||
if (!folder.exists()) {
|
||||
if (!folder.mkdirs()) {
|
||||
throw new RuntimeException("Error while creating userdata directory!");
|
||||
@@ -59,9 +60,12 @@ public class Economy {
|
||||
npcConfig.load();
|
||||
npcConfig.setProperty("npc", true);
|
||||
npcConfig.setProperty("last-account-name", name);
|
||||
npcConfig.setProperty("npc-name", unsanitizedName);
|
||||
npcConfig.setProperty("money", ess.getSettings().getStartingBalance());
|
||||
npcConfig.blockingSave();
|
||||
ess.getUserMap().trackUUID(npcUUID, name, false);
|
||||
// This will load the NPC into the UserMap + UUID cache
|
||||
((ModernUserMap) ess.getUsers()).addCachedNpcName(npcUUID, name);
|
||||
ess.getUsers().getUser(npcUUID);
|
||||
}
|
||||
|
||||
private static void deleteNPC(final String name) {
|
||||
|
||||
@@ -64,8 +64,8 @@ public class Commandbalancetop extends EssentialsCommand {
|
||||
}
|
||||
|
||||
// If there are less than 50 users in our usermap, there is no need to display a warning as these calculations should be done quickly
|
||||
if (ess.getUserMap().getUniqueUsers() > MINUSERS) {
|
||||
sender.sendMessage(tl("orderBalances", ess.getUserMap().getUniqueUsers()));
|
||||
if (ess.getUsers().getUserCount() > MINUSERS) {
|
||||
sender.sendMessage(tl("orderBalances", ess.getUsers().getUserCount()));
|
||||
}
|
||||
|
||||
ess.runTaskAsynchronously(new Viewer(sender, page, force));
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.OfflinePlayer;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import org.bukkit.BanList;
|
||||
@@ -30,7 +30,7 @@ public class Commandban extends EssentialsCommand {
|
||||
user = getPlayer(server, args, 0, true, true);
|
||||
} catch (final PlayerNotFoundException e) {
|
||||
nomatch = true;
|
||||
user = ess.getUser(new OfflinePlayer(args[0], ess.getServer()));
|
||||
user = ess.getUser(new OfflinePlayerStub(args[0], ess.getServer()));
|
||||
}
|
||||
if (!user.getBase().isOnline()) {
|
||||
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.ban.offline")) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Material;
|
||||
@@ -25,7 +25,7 @@ public class Commandbook extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
final ItemStack item = user.getItemInHand();
|
||||
final ItemStack item = Inventories.getItemInMainHand(user.getBase());
|
||||
final String player = user.getName();
|
||||
if (item.getType() == Material.WRITTEN_BOOK) {
|
||||
final BookMeta bmeta = (BookMeta) item.getItemMeta();
|
||||
@@ -52,7 +52,7 @@ public class Commandbook extends EssentialsCommand {
|
||||
if (isAuthor(bmeta, player) || user.isAuthorized("essentials.book.others")) {
|
||||
final ItemStack newItem = new ItemStack(WRITABLE_BOOK, item.getAmount());
|
||||
newItem.setItemMeta(bmeta);
|
||||
InventoryWorkaround.setItemInMainHand(user.getBase(), newItem);
|
||||
Inventories.setItemInMainHand(user.getBase(), newItem);
|
||||
user.sendMessage(tl("editBookContents"));
|
||||
} else {
|
||||
throw new Exception(tl("denyBookEdit"));
|
||||
@@ -65,7 +65,7 @@ public class Commandbook extends EssentialsCommand {
|
||||
}
|
||||
final ItemStack newItem = new ItemStack(Material.WRITTEN_BOOK, item.getAmount());
|
||||
newItem.setItemMeta(bmeta);
|
||||
InventoryWorkaround.setItemInMainHand(user.getBase(), newItem);
|
||||
Inventories.setItemInMainHand(user.getBase(), newItem);
|
||||
user.sendMessage(tl("bookLocked"));
|
||||
} else {
|
||||
throw new Exception(tl("holdBook"));
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class Commandbottom extends EssentialsCommand {
|
||||
|
||||
public Commandbottom() {
|
||||
super("bottom");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
final int bottomX = user.getLocation().getBlockX();
|
||||
final int bottomZ = user.getLocation().getBlockZ();
|
||||
final float pitch = user.getLocation().getPitch();
|
||||
final float yaw = user.getLocation().getYaw();
|
||||
final Location unsafe = new Location(user.getWorld(), bottomX, ess.getWorldInfoProvider().getMinHeight(user.getWorld()), bottomZ, yaw, pitch);
|
||||
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
|
||||
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportBottom", safe.getWorld().getName(), safe.getBlockX(), safe.getBlockY(), safe.getBlockZ()));
|
||||
}
|
||||
});
|
||||
user.getAsyncTeleport().teleport(safe, new Trade(this.getName(), ess), PlayerTeleportEvent.TeleportCause.COMMAND, future);
|
||||
}
|
||||
}
|
||||
+10
-20
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -22,8 +22,6 @@ import java.util.Set;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class Commandclearinventory extends EssentialsCommand {
|
||||
|
||||
private static final int BASE_AMOUNT = 100000;
|
||||
private static final int EXTENDED_CAP = 8;
|
||||
|
||||
public Commandclearinventory() {
|
||||
@@ -114,38 +112,30 @@ public class Commandclearinventory extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ClearHandlerType.ALL_EXCEPT_ARMOR) {
|
||||
if (type != ClearHandlerType.SPECIFIC_ITEM) {
|
||||
final boolean armor = type == ClearHandlerType.ALL_INCLUDING_ARMOR;
|
||||
if (showExtended) {
|
||||
sender.sendMessage(tl("inventoryClearingAllItems", player.getDisplayName()));
|
||||
sender.sendMessage(tl(armor ? "inventoryClearingAllArmor" : "inventoryClearingAllItems", player.getDisplayName()));
|
||||
}
|
||||
InventoryWorkaround.clearInventoryNoArmor(player.getInventory());
|
||||
InventoryWorkaround.setItemInOffHand(player, null);
|
||||
} else if (type == ClearHandlerType.ALL_INCLUDING_ARMOR) {
|
||||
if (showExtended) {
|
||||
sender.sendMessage(tl("inventoryClearingAllArmor", player.getDisplayName()));
|
||||
}
|
||||
InventoryWorkaround.clearInventoryNoArmor(player.getInventory());
|
||||
InventoryWorkaround.setItemInOffHand(player, null);
|
||||
player.getInventory().setArmorContents(null);
|
||||
Inventories.removeItems(player, item -> true, armor);
|
||||
} else {
|
||||
for (final Item item : items) {
|
||||
final ItemStack stack = new ItemStack(item.getMaterial());
|
||||
if (VersionUtil.PRE_FLATTENING) {
|
||||
//noinspection deprecation
|
||||
stack.setDurability(item.getData());
|
||||
}
|
||||
|
||||
// amount -1 means all items will be cleared
|
||||
if (amount == -1) {
|
||||
stack.setAmount(BASE_AMOUNT);
|
||||
final ItemStack removedStack = player.getInventory().removeItem(stack).get(0);
|
||||
final int removedAmount = BASE_AMOUNT - removedStack.getAmount() + InventoryWorkaround.clearItemInOffHand(player, stack);
|
||||
final int removedAmount = Inventories.removeItemSimilar(player, stack, true);
|
||||
if (removedAmount > 0 || showExtended) {
|
||||
sender.sendMessage(tl("inventoryClearingStack", removedAmount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
|
||||
}
|
||||
} else {
|
||||
stack.setAmount(amount < 0 ? 1 : amount);
|
||||
if (player.getInventory().containsAtLeast(stack, amount)) {
|
||||
if (Inventories.removeItemAmount(player, stack, amount)) {
|
||||
sender.sendMessage(tl("inventoryClearingStack", amount, stack.getType().toString().toLowerCase(Locale.ENGLISH), player.getDisplayName()));
|
||||
player.getInventory().removeItem(stack);
|
||||
} else {
|
||||
if (showExtended) {
|
||||
sender.sendMessage(tl("inventoryClearFail", player.getDisplayName(), amount, stack.getType().toString().toLowerCase(Locale.ENGLISH)));
|
||||
@@ -203,7 +193,7 @@ public class Commandclearinventory extends EssentialsCommand {
|
||||
}
|
||||
|
||||
private String formatCommand(final String commandLabel, final String[] args) {
|
||||
return "/" + commandLabel + " " + StringUtil.joinList(" ", args);
|
||||
return "/" + commandLabel + " " + StringUtil.joinList(" ", (Object[]) args);
|
||||
}
|
||||
|
||||
private enum ClearHandlerType {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.Trade.OverflowType;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import org.bukkit.Material;
|
||||
@@ -39,7 +40,7 @@ public class Commandcondense extends EssentialsCommand {
|
||||
if (args.length > 0) {
|
||||
is = ess.getItemDb().getMatching(user, args);
|
||||
} else {
|
||||
for (final ItemStack stack : user.getBase().getInventory().getContents()) {
|
||||
for (final ItemStack stack : Inventories.getInventory(user.getBase(), false)) {
|
||||
if (stack == null || stack.getType() == Material.AIR) {
|
||||
continue;
|
||||
}
|
||||
@@ -85,7 +86,7 @@ public class Commandcondense extends EssentialsCommand {
|
||||
|
||||
int amount = 0;
|
||||
|
||||
for (final ItemStack contents : user.getBase().getInventory().getContents()) {
|
||||
for (final ItemStack contents : Inventories.getInventory(user.getBase(), false)) {
|
||||
if (contents != null && contents.isSimilar(stack)) {
|
||||
amount += contents.getAmount();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.PasteUtil;
|
||||
import org.bukkit.Material;
|
||||
@@ -37,7 +38,7 @@ public class Commandcreatekit extends EssentialsCommand {
|
||||
// Command handler will auto fail if this fails.
|
||||
final long delay = Long.parseLong(args[1]);
|
||||
final String kitname = args[0];
|
||||
final ItemStack[] items = user.getBase().getInventory().getContents();
|
||||
final ItemStack[] items = Inventories.getInventory(user.getBase(), true);
|
||||
final List<String> list = new ArrayList<>();
|
||||
|
||||
boolean useSerializationProvider = ess.getSettings().isUseBetterKits();
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.IUser;
|
||||
import com.earth2me.essentials.User;
|
||||
import net.essentialsx.api.v2.events.HomeModifyEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -37,18 +39,27 @@ public class Commanddelhome extends EssentialsCommand {
|
||||
|
||||
if (expandedArg.length > 1 && (user == null || user.isAuthorized("essentials.delhome.others"))) {
|
||||
user = getPlayer(server, expandedArg, 0, true, true);
|
||||
name = expandedArg[1];
|
||||
name = expandedArg[1].toLowerCase(Locale.ENGLISH);
|
||||
} else if (user == null) {
|
||||
throw new NotEnoughArgumentsException();
|
||||
} else {
|
||||
name = expandedArg[0];
|
||||
name = expandedArg[0].toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
if (name.equalsIgnoreCase("bed")) {
|
||||
if (name.equals("bed")) {
|
||||
throw new Exception(tl("invalidHomeName"));
|
||||
}
|
||||
|
||||
user.delHome(name.toLowerCase(Locale.ENGLISH));
|
||||
final HomeModifyEvent event = new HomeModifyEvent(sender.getUser(ess), user, name, user.getHome(name), false);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("HomeModifyEvent canceled for /delhome execution by " + sender.getDisplayName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
user.delHome(name);
|
||||
sender.sendMessage(tl("deleteHome", name));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,22 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.HangingSign;
|
||||
import org.bukkit.block.data.type.WallHangingSign;
|
||||
import org.bukkit.block.data.type.WallSign;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -29,48 +40,74 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
if (!(target.getState() instanceof Sign)) {
|
||||
throw new Exception(tl("editsignCommandTarget"));
|
||||
}
|
||||
final Sign sign = (Sign) target.getState();
|
||||
final ModifiableSign sign = wrapSign((Sign) target.getState(), user);
|
||||
try {
|
||||
if (args[0].equalsIgnoreCase("set") && args.length > 2) {
|
||||
final String[] existingLines = sign.getLines();
|
||||
final int line = Integer.parseInt(args[1]) - 1;
|
||||
final String text = FormatUtil.formatString(user, "essentials.editsign", getFinalArg(args, 2)).trim();
|
||||
if (ChatColor.stripColor(text).length() > 15 && !user.isAuthorized("essentials.editsign.unlimited")) {
|
||||
throw new Exception(tl("editsignCommandLimit"));
|
||||
}
|
||||
sign.setLine(line, text);
|
||||
sign.update();
|
||||
existingLines[line] = text;
|
||||
if (callSignEvent(sign, user.getBase(), existingLines)) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.sendMessage(tl("editsignCommandSetSuccess", line + 1, text));
|
||||
} else if (args[0].equalsIgnoreCase("clear")) {
|
||||
if (args.length == 1) {
|
||||
final String[] existingLines = sign.getLines();
|
||||
for (int i = 0; i < 4; i++) { // A whole one line of line savings!
|
||||
sign.setLine(i, "");
|
||||
existingLines[i] = "";
|
||||
}
|
||||
sign.update();
|
||||
|
||||
if (callSignEvent(sign, user.getBase(), existingLines)) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.sendMessage(tl("editsignCommandClear"));
|
||||
} else {
|
||||
final String[] existingLines = sign.getLines();
|
||||
final int line = Integer.parseInt(args[1]) - 1;
|
||||
sign.setLine(line, "");
|
||||
sign.update();
|
||||
existingLines[line] = "";
|
||||
|
||||
if (callSignEvent(sign, user.getBase(), existingLines)) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.sendMessage(tl("editsignCommandClearLine", line + 1));
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("copy") || args[0].equalsIgnoreCase("paste")) {
|
||||
final boolean copy = args[0].equalsIgnoreCase("copy");
|
||||
final String tlPrefix = copy ? "editsignCopy" : "editsignPaste";
|
||||
} else if (args[0].equalsIgnoreCase("copy")) {
|
||||
final int line = args.length == 1 ? -1 : Integer.parseInt(args[1]) - 1;
|
||||
|
||||
if (line == -1) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
processSignCopyPaste(user, sign, i, copy);
|
||||
// We use unformat here to prevent players from copying signs with colors that they do not have permission to use.
|
||||
user.getSignCopy().set(i, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(i)));
|
||||
}
|
||||
user.sendMessage(tl(tlPrefix, commandLabel));
|
||||
user.sendMessage(tl("editsignCopy", commandLabel));
|
||||
} else {
|
||||
processSignCopyPaste(user, sign, line, copy);
|
||||
user.sendMessage(tl(tlPrefix + "Line", line + 1, commandLabel));
|
||||
// We use unformat here to prevent players from copying signs with colors that they do not have permission to use.
|
||||
user.getSignCopy().set(line, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(line)));
|
||||
user.sendMessage(tl("editsignCopyLine", line + 1, commandLabel));
|
||||
}
|
||||
|
||||
if (!copy) {
|
||||
sign.update();
|
||||
} else if (args[0].equalsIgnoreCase("paste")) {
|
||||
final int line = args.length == 1 ? -1 : Integer.parseInt(args[1]) - 1;
|
||||
|
||||
final String[] existingLines = sign.getLines();
|
||||
if (line == -1) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
existingLines[i] = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(i));
|
||||
}
|
||||
user.sendMessage(tl("editsignPaste", commandLabel));
|
||||
} else {
|
||||
existingLines[line] = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(line));
|
||||
user.sendMessage(tl("editsignPasteLine", line + 1, commandLabel));
|
||||
}
|
||||
|
||||
callSignEvent(sign, user.getBase(), existingLines);
|
||||
} else {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
@@ -79,15 +116,28 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private void processSignCopyPaste(final User user, final Sign sign, final int index, final boolean copy) {
|
||||
if (copy) {
|
||||
// We use unformat here to prevent players from copying signs with colors that they do not have permission to use.
|
||||
user.getSignCopy().set(index, FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(index)));
|
||||
return;
|
||||
private boolean callSignEvent(final ModifiableSign sign, final Player player, final String[] lines) {
|
||||
final SignChangeEvent event;
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
|
||||
event = new SignChangeEvent(sign.getBlock(), player, lines, sign.isFront() ? Side.FRONT : Side.BACK);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
event = new SignChangeEvent(sign.getBlock(), player, lines);
|
||||
}
|
||||
|
||||
final String line = FormatUtil.formatString(user, "essentials.editsign", user.getSignCopy().get(index));
|
||||
sign.setLine(index, line == null ? "" : line);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("SignChangeEvent canceled for /editsign execution by " + player.getName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sign.setLine(i, lines[i]);
|
||||
}
|
||||
sign.update();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +150,7 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
final int line = Integer.parseInt(args[1]);
|
||||
final Block target = user.getTargetBlock(5);
|
||||
if (target.getState() instanceof Sign && line <= 4) {
|
||||
final Sign sign = (Sign) target.getState();
|
||||
final ModifiableSign sign = wrapSign((Sign) target.getState(), user);
|
||||
return Lists.newArrayList(FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(line - 1)));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
@@ -108,4 +158,93 @@ public class Commandeditsign extends EssentialsCommand {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private ModifiableSign wrapSign(final Sign sign, final User user) {
|
||||
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
|
||||
final Vector eyeLocLessSign = user.getBase().getEyeLocation().toVector().subtract(sign.getLocation().add(.5, .5, .5).toVector());
|
||||
final BlockData signBlockData = sign.getBlockData();
|
||||
|
||||
final BlockFace signDirection;
|
||||
if (signBlockData instanceof org.bukkit.block.data.type.Sign) {
|
||||
signDirection = ((org.bukkit.block.data.type.Sign) signBlockData).getRotation();
|
||||
} else if (signBlockData instanceof WallSign) {
|
||||
signDirection = ((WallSign) signBlockData).getFacing();
|
||||
} else if (signBlockData instanceof HangingSign) {
|
||||
signDirection = ((HangingSign) signBlockData).getRotation();
|
||||
} else if (signBlockData instanceof WallHangingSign) {
|
||||
signDirection = ((WallHangingSign) signBlockData).getFacing();
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown block data for sign: " + signBlockData.getClass());
|
||||
}
|
||||
|
||||
final Side side = eyeLocLessSign.dot(signDirection.getDirection()) > 0 ? Side.FRONT : Side.BACK;
|
||||
|
||||
return new ModifiableSign(sign) {
|
||||
@Override
|
||||
String[] getLines() {
|
||||
return sign.getSide(side).getLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getLine(int line) {
|
||||
return sign.getSide(side).getLine(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setLine(int line, String text) {
|
||||
sign.getSide(side).setLine(line, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFront() {
|
||||
return side == Side.FRONT;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new ModifiableSign(sign) {
|
||||
@Override
|
||||
String[] getLines() {
|
||||
return sign.getLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getLine(int line) {
|
||||
return sign.getLine(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setLine(int line, String text) {
|
||||
sign.setLine(line, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFront() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private abstract static class ModifiableSign {
|
||||
protected final Sign sign;
|
||||
|
||||
protected ModifiableSign(final Sign sign) {
|
||||
this.sign = sign;
|
||||
}
|
||||
|
||||
abstract String getLine(int line);
|
||||
|
||||
abstract String[] getLines();
|
||||
|
||||
abstract void setLine(int line, String text);
|
||||
|
||||
abstract boolean isFront();
|
||||
|
||||
Block getBlock() {
|
||||
return sign.getBlock();
|
||||
}
|
||||
|
||||
void update() {
|
||||
sign.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.Enchantments;
|
||||
import com.earth2me.essentials.MetaItemStack;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Material;
|
||||
@@ -57,7 +56,7 @@ public class Commandenchant extends EssentialsCommand {
|
||||
final MetaItemStack metaStack = new MetaItemStack(stack);
|
||||
final Enchantment enchantment = metaStack.getEnchantment(user, args[0]);
|
||||
metaStack.addEnchantment(user.getSource(), ess.getSettings().allowUnsafeEnchantments() && user.isAuthorized("essentials.enchantments.allowunsafe"), enchantment, level);
|
||||
InventoryWorkaround.setItemInMainHand(user.getBase(), metaStack.getItemStack());
|
||||
stack.setItemMeta(metaStack.getItemStack().getItemMeta());
|
||||
user.getBase().updateInventory();
|
||||
final String enchantName = enchantment.getName().toLowerCase(Locale.ENGLISH).replace('_', ' ');
|
||||
if (level == 0) {
|
||||
|
||||
@@ -3,9 +3,10 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.EssentialsUpgrade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.UserMap;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.economy.EconomyLayer;
|
||||
import com.earth2me.essentials.economy.EconomyLayers;
|
||||
import com.earth2me.essentials.userstorage.ModernUserMap;
|
||||
import com.earth2me.essentials.utils.CommandMapUtil;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
@@ -13,7 +14,6 @@ import com.earth2me.essentials.utils.FloatUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.PasteUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonArray;
|
||||
@@ -23,16 +23,19 @@ import com.google.gson.JsonPrimitive;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -45,12 +48,15 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
@@ -90,6 +96,7 @@ public class Commandessentials extends EssentialsCommand {
|
||||
"EssentialsAntiBuild",
|
||||
"EssentialsChat",
|
||||
"EssentialsDiscord",
|
||||
"EssentialsDiscordLink",
|
||||
"EssentialsGeoIP",
|
||||
"EssentialsProtect",
|
||||
"EssentialsSpawn",
|
||||
@@ -147,11 +154,12 @@ public class Commandessentials extends EssentialsCommand {
|
||||
case "homes":
|
||||
runHomes(server, sender, commandLabel, args);
|
||||
break;
|
||||
case "uuidconvert":
|
||||
runUUIDConvert(server, sender, commandLabel, args);
|
||||
case "usermap":
|
||||
runUserMap(sender, args);
|
||||
break;
|
||||
case "uuidtest":
|
||||
runUUIDTest(server, sender, commandLabel, args);
|
||||
|
||||
case "itemtest":
|
||||
runItemTest(server, sender, commandLabel, args);
|
||||
break;
|
||||
|
||||
// "#EasterEgg"
|
||||
@@ -168,6 +176,56 @@ public class Commandessentials extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
public void runItemTest(Server server, CommandSource sender, String commandLabel, String[] args) {
|
||||
if (!sender.isAuthorized("essentials.itemtest", ess) || args.length < 2 || !sender.isPlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = sender.getPlayer();
|
||||
assert player != null;
|
||||
|
||||
switch (args[1]) {
|
||||
case "slot": {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
player.getInventory().setItem(Integer.parseInt(args[2]), new ItemStack(Material.DIRT));
|
||||
break;
|
||||
}
|
||||
case "overfill": {
|
||||
sender.sendMessage(Inventories.addItem(player, 42, false, new ItemStack(Material.DIAMOND_SWORD, 1), new ItemStack(Material.DIRT, 32), new ItemStack(Material.DIRT, 32)).toString());
|
||||
break;
|
||||
}
|
||||
case "overfill2": {
|
||||
if (args.length < 4) {
|
||||
return;
|
||||
}
|
||||
final boolean armor = Boolean.parseBoolean(args[2]);
|
||||
final boolean add = Boolean.parseBoolean(args[3]);
|
||||
final ItemStack[] items = new ItemStack[]{new ItemStack(Material.DIAMOND_SWORD, 1), new ItemStack(Material.DIRT, 32), new ItemStack(Material.DIRT, 32), new ItemStack(Material.DIAMOND_HELMET, 4), new ItemStack(Material.CHAINMAIL_LEGGINGS, 1)};
|
||||
if (Inventories.hasSpace(player, 0, armor, items)) {
|
||||
if (add) {
|
||||
sender.sendMessage(Inventories.addItem(player, 0, armor, items).toString());
|
||||
}
|
||||
sender.sendMessage("SO MUCH SPACE!");
|
||||
} else {
|
||||
sender.sendMessage("No space!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "remove": {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Inventories.removeItemExact(player, new ItemStack(Material.PUMPKIN, 1), Boolean.parseBoolean(args[2]));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Displays the command's usage.
|
||||
private void showUsage(final CommandSource sender) throws Exception {
|
||||
throw new NotEnoughArgumentsException();
|
||||
@@ -270,6 +328,7 @@ public class Commandessentials extends EssentialsCommand {
|
||||
files.add(new PasteUtil.PasteFile("dump.json", dump.toString()));
|
||||
|
||||
final Plugin essDiscord = Bukkit.getPluginManager().getPlugin("EssentialsDiscord");
|
||||
final Plugin essDiscordLink = Bukkit.getPluginManager().getPlugin("EssentialsDiscordLink");
|
||||
final Plugin essSpawn = Bukkit.getPluginManager().getPlugin("EssentialsSpawn");
|
||||
|
||||
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.getKnownCommandsProvider().getKnownCommands());
|
||||
@@ -331,6 +390,15 @@ public class Commandessentials extends EssentialsCommand {
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage(tl("dumpErrorUpload", "discord-config.yml", e.getMessage()));
|
||||
}
|
||||
|
||||
if (essDiscordLink != null) {
|
||||
try {
|
||||
files.add(new PasteUtil.PasteFile("discord-link-config.yml",
|
||||
new String(Files.readAllBytes(essDiscordLink.getDataFolder().toPath().resolve("config.yml")), StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage(tl("dumpErrorUpload", "discord-link-config.yml", e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kits) {
|
||||
@@ -473,12 +541,11 @@ public class Commandessentials extends EssentialsCommand {
|
||||
final long daysArg = Long.parseLong(args[1]);
|
||||
final double moneyArg = args.length >= 3 ? FloatUtil.parseDouble(args[2].replaceAll("[^0-9\\.]", "")) : 0;
|
||||
final int homesArg = args.length >= 4 && NumberUtil.isInt(args[3]) ? Integer.parseInt(args[3]) : 0;
|
||||
final UserMap userMap = ess.getUserMap();
|
||||
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
final long currTime = System.currentTimeMillis();
|
||||
for (final UUID u : userMap.getAllUniqueUsers()) {
|
||||
final User user = ess.getUserMap().getUser(u);
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -523,13 +590,12 @@ public class Commandessentials extends EssentialsCommand {
|
||||
throw new Exception(HOMES_USAGE);
|
||||
}
|
||||
|
||||
final UserMap userMap = ess.getUserMap();
|
||||
switch (args[1]) {
|
||||
case "fix":
|
||||
sender.sendMessage(tl("fixingHomes"));
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final UUID u : userMap.getAllUniqueUsers()) {
|
||||
final User user = ess.getUserMap().getUser(u);
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -553,8 +619,8 @@ public class Commandessentials extends EssentialsCommand {
|
||||
}
|
||||
sender.sendMessage(filterByWorld ? tl("deletingHomesWorld", args[2]) : tl("deletingHomes"));
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
for (final UUID u : userMap.getAllUniqueUsers()) {
|
||||
final User user = ess.getUserMap().getUser(u);
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -577,52 +643,79 @@ public class Commandessentials extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
// Forces a rerun of userdata UUID conversion.
|
||||
private void runUUIDConvert(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
sender.sendMessage("Starting Essentials UUID userdata conversion; this may lag the server.");
|
||||
|
||||
final Boolean ignoreUFCache = args.length > 2 && args[1].toLowerCase(Locale.ENGLISH).contains("ignore");
|
||||
EssentialsUpgrade.uuidFileConvert(ess, ignoreUFCache);
|
||||
|
||||
sender.sendMessage("UUID conversion complete. Check your server log for more information.");
|
||||
}
|
||||
|
||||
// Looks up various UUIDs for a user.
|
||||
private void runUUIDTest(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
if (args.length < 2) {
|
||||
throw new Exception("/<command> uuidtest <name>");
|
||||
// Gets information about cached users
|
||||
private void runUserMap(final CommandSource sender, final String[] args) {
|
||||
if (!sender.isAuthorized("essentials.usermap", ess)) {
|
||||
return;
|
||||
}
|
||||
final String name = args[1];
|
||||
sender.sendMessage("Looking up UUID for " + name);
|
||||
|
||||
UUID onlineUUID = null;
|
||||
final ModernUserMap userMap = (ModernUserMap) ess.getUsers();
|
||||
sender.sendMessage(tl("usermapSize", userMap.getCachedCount(), userMap.getUserCount(), ess.getSettings().getMaxUserCacheCount()));
|
||||
if (args.length > 1) {
|
||||
if (args[1].equals("full")) {
|
||||
for (final Map.Entry<String, UUID> entry : userMap.getNameCache().entrySet()) {
|
||||
sender.sendMessage(tl("usermapEntry", entry.getKey(), entry.getValue().toString()));
|
||||
}
|
||||
} else if (args[1].equals("purge")) {
|
||||
final boolean seppuku = args.length > 2 && args[2].equals("iknowwhatimdoing");
|
||||
|
||||
for (final Player player : ess.getOnlinePlayers()) {
|
||||
if (player.getName().equalsIgnoreCase(name)) {
|
||||
onlineUUID = player.getUniqueId();
|
||||
break;
|
||||
sender.sendMessage(tl("usermapPurge", String.valueOf(seppuku)));
|
||||
|
||||
final Set<UUID> uuids = new HashSet<>(ess.getUsers().getAllUserUUIDs());
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
final File userdataFolder = new File(ess.getDataFolder(), "userdata");
|
||||
final File backupFolder = new File(ess.getDataFolder(), "userdata-npc-backup-boogaloo-" + System.currentTimeMillis());
|
||||
|
||||
if (!userdataFolder.isDirectory()) {
|
||||
ess.getLogger().warning("Missing userdata folder, aborting usermap purge.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (seppuku && !backupFolder.mkdir()) {
|
||||
ess.getLogger().warning("Unable to create backup folder, aborting usermap purge.");
|
||||
return;
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
final File[] files = userdataFolder.listFiles(EssentialsUpgrade.YML_FILTER);
|
||||
if (files != null) {
|
||||
for (final File file : files) {
|
||||
try {
|
||||
final String fileName = file.getName();
|
||||
final UUID uuid = UUID.fromString(fileName.substring(0, fileName.length() - 4));
|
||||
if (!uuids.contains(uuid)) {
|
||||
total++;
|
||||
ess.getLogger().warning("Found orphaned userdata file: " + file.getName());
|
||||
if (seppuku) {
|
||||
try {
|
||||
com.google.common.io.Files.move(file, new File(backupFolder, file.getName()));
|
||||
} catch (IOException e) {
|
||||
ess.getLogger().log(Level.WARNING, "Unable to move orphaned userdata file: " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ess.getLogger().info("Found " + total + " orphaned userdata files.");
|
||||
});
|
||||
} else if (args[1].equalsIgnoreCase("cache")) {
|
||||
sender.sendMessage(tl("usermapKnown", ess.getUsers().getAllUserUUIDs().size(), ess.getUsers().getNameCache().size()));
|
||||
} else {
|
||||
try {
|
||||
final UUID uuid = UUID.fromString(args[1]);
|
||||
for (final Map.Entry<String, UUID> entry : userMap.getNameCache().entrySet()) {
|
||||
if (entry.getValue().equals(uuid)) {
|
||||
sender.sendMessage(tl("usermapEntry", entry.getKey(), args[1]));
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
final String sanitizedName = userMap.getSanitizedName(args[1]);
|
||||
sender.sendMessage(tl("usermapEntry", sanitizedName, userMap.getNameCache().get(sanitizedName).toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final UUID essUUID = ess.getUserMap().getUser(name).getConfigUUID();
|
||||
|
||||
final org.bukkit.OfflinePlayer player = ess.getServer().getOfflinePlayer(name);
|
||||
final UUID bukkituuid = player.getUniqueId();
|
||||
sender.sendMessage("Bukkit Lookup: " + bukkituuid.toString());
|
||||
|
||||
if (onlineUUID != null && onlineUUID != bukkituuid) {
|
||||
sender.sendMessage("Online player: " + onlineUUID.toString());
|
||||
}
|
||||
|
||||
if (essUUID != null && essUUID != bukkituuid) {
|
||||
sender.sendMessage("Essentials config: " + essUUID.toString());
|
||||
}
|
||||
|
||||
final UUID npcuuid = UUID.nameUUIDFromBytes(("NPC:" + name).getBytes(Charsets.UTF_8));
|
||||
sender.sendMessage("NPC UUID: " + npcuuid.toString());
|
||||
|
||||
final UUID offlineuuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8));
|
||||
sender.sendMessage("Offline Mode UUID: " + offlineuuid.toString());
|
||||
}
|
||||
|
||||
// Displays versions of EssentialsX and related plugins.
|
||||
@@ -750,7 +843,6 @@ public class Commandessentials extends EssentialsCommand {
|
||||
options.add("cleanup");
|
||||
options.add("homes");
|
||||
//options.add("uuidconvert");
|
||||
//options.add("uuidtest");
|
||||
//options.add("nya");
|
||||
//options.add("moo");
|
||||
return options;
|
||||
@@ -763,7 +855,6 @@ public class Commandessentials extends EssentialsCommand {
|
||||
}
|
||||
break;
|
||||
case "reset":
|
||||
case "uuidtest":
|
||||
if (args.length == 2) {
|
||||
return getPlayers(server, sender);
|
||||
}
|
||||
@@ -782,11 +873,6 @@ public class Commandessentials extends EssentialsCommand {
|
||||
return server.getWorlds().stream().map(World::getName).collect(Collectors.toList());
|
||||
}
|
||||
break;
|
||||
case "uuidconvert":
|
||||
if (args.length == 2) {
|
||||
return Lists.newArrayList("ignoreUFCache");
|
||||
}
|
||||
break;
|
||||
case "dump":
|
||||
final List<String> list = Lists.newArrayList("config", "kits", "log", "discord", "worth", "tpr", "spawns", "commands", "all");
|
||||
for (String arg : args) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.MetaItemStack;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -81,13 +81,8 @@ public class Commandgive extends EssentialsLoopCommand {
|
||||
final ItemStack finalStack = stack;
|
||||
loopOnlinePlayersConsumer(server, sender, false, true, args[0], player -> {
|
||||
sender.sendMessage(tl("giveSpawn", finalStack.getAmount(), itemName, player.getDisplayName()));
|
||||
final Map<Integer, ItemStack> leftovers;
|
||||
|
||||
if (player.isAuthorized("essentials.oversizedstacks")) {
|
||||
leftovers = InventoryWorkaround.addOversizedItems(player.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), finalStack);
|
||||
} else {
|
||||
leftovers = InventoryWorkaround.addItems(player.getBase().getInventory(), finalStack);
|
||||
}
|
||||
final Map<Integer, ItemStack> leftovers = Inventories.addItem(player.getBase(), player.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0, finalStack);
|
||||
|
||||
for (final ItemStack item : leftovers.values()) {
|
||||
if (isDropItemsIfFull) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.TriState;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -28,7 +28,7 @@ public class Commandhat extends EssentialsCommand {
|
||||
@Override
|
||||
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
if (args.length == 0 || (!args[0].contains("rem") && !args[0].contains("off") && !args[0].equalsIgnoreCase("0"))) {
|
||||
final ItemStack hand = user.getItemInHand();
|
||||
final ItemStack hand = Inventories.getItemInMainHand(user.getBase());
|
||||
if (hand == null || hand.getType() == Material.AIR) {
|
||||
user.sendMessage(tl("hatFail"));
|
||||
return;
|
||||
@@ -53,7 +53,7 @@ public class Commandhat extends EssentialsCommand {
|
||||
return;
|
||||
}
|
||||
inv.setHelmet(hand);
|
||||
inv.setItemInHand(head);
|
||||
Inventories.setItemInMainHand(user.getBase(), head);
|
||||
user.sendMessage(tl("hatPlaced"));
|
||||
return;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class Commandhat extends EssentialsCommand {
|
||||
} else {
|
||||
final ItemStack air = new ItemStack(Material.AIR);
|
||||
inv.setHelmet(air);
|
||||
InventoryWorkaround.addItems(user.getBase().getInventory(), head);
|
||||
Inventories.addItem(user.getBase(), head);
|
||||
user.sendMessage(tl("hatRemoved"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.OfflinePlayer;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
@@ -42,7 +42,7 @@ public class Commandhome extends EssentialsCommand {
|
||||
}
|
||||
try {
|
||||
if ("bed".equalsIgnoreCase(homeName) && user.isAuthorized("essentials.home.bed")) {
|
||||
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayer) {
|
||||
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayerStub) {
|
||||
throw new Exception(tl("bedOffline"));
|
||||
}
|
||||
PaperLib.getBedSpawnLocationAsync(player.getBase(), true).thenAccept(location -> {
|
||||
@@ -101,7 +101,7 @@ public class Commandhome extends EssentialsCommand {
|
||||
user.sendMessage(tl("homes", StringUtil.joinList(homes), count, getHomeLimit(finalPlayer)));
|
||||
}
|
||||
});
|
||||
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayer) {
|
||||
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayerStub) {
|
||||
message.complete(null);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.MetaItemStack;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
@@ -63,11 +63,7 @@ public class Commanditem extends EssentialsCommand {
|
||||
|
||||
final String displayName = stack.getType().toString().toLowerCase(Locale.ENGLISH).replace('_', ' ');
|
||||
user.sendMessage(tl("itemSpawn", stack.getAmount(), displayName));
|
||||
if (user.isAuthorized("essentials.oversizedstacks")) {
|
||||
InventoryWorkaround.addOversizedItems(user.getBase().getInventory(), ess.getSettings().getOversizedStackSize(), stack);
|
||||
} else {
|
||||
InventoryWorkaround.addItems(user.getBase().getInventory(), stack);
|
||||
}
|
||||
Inventories.addItem(user.getBase(), user.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0, stack);
|
||||
user.getBase().updateInventory();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
@@ -24,8 +25,8 @@ public class Commanditemlore extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
final ItemStack item = user.getBase().getItemInHand();
|
||||
if (MaterialUtil.isAir(item.getType())) {
|
||||
final ItemStack item = Inventories.getItemInHand(user.getBase());
|
||||
if (item == null || MaterialUtil.isAir(item.getType())) {
|
||||
throw new Exception(tl("itemloreInvalidItem"));
|
||||
}
|
||||
|
||||
@@ -73,8 +74,8 @@ public class Commanditemlore extends EssentialsCommand {
|
||||
} else if (args.length == 2) {
|
||||
switch (args[0].toLowerCase(Locale.ENGLISH)) {
|
||||
case "set": {
|
||||
final ItemStack item = user.getBase().getItemInHand();
|
||||
if (!MaterialUtil.isAir(item.getType()) && item.hasItemMeta() && item.getItemMeta().hasLore()) {
|
||||
final ItemStack item = Inventories.getItemInHand(user.getBase());
|
||||
if (item != null && !MaterialUtil.isAir(item.getType()) && item.hasItemMeta() && item.getItemMeta().hasLore()) {
|
||||
final List<String> lineNumbers = new ArrayList<>();
|
||||
for (int i = 1; i <= item.getItemMeta().getLore().size(); i++) {
|
||||
lineNumbers.add(String.valueOf(i));
|
||||
@@ -92,8 +93,8 @@ public class Commanditemlore extends EssentialsCommand {
|
||||
} else if (args.length == 3) {
|
||||
if (args[0].equalsIgnoreCase("set") && NumberUtil.isInt(args[1])) {
|
||||
final int i = Integer.parseInt(args[1]);
|
||||
final ItemStack item = user.getBase().getItemInHand();
|
||||
if (!MaterialUtil.isAir(item.getType()) && item.hasItemMeta() && item.getItemMeta().hasLore() && item.getItemMeta().getLore().size() >= i) {
|
||||
final ItemStack item = Inventories.getItemInHand(user.getBase());
|
||||
if (item != null && !MaterialUtil.isAir(item.getType()) && item.hasItemMeta() && item.getItemMeta().hasLore() && item.getItemMeta().getLore().size() >= i) {
|
||||
return Lists.newArrayList(FormatUtil.unformatString(user, "essentials.itemlore", item.getItemMeta().getLore().get(i - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.TriState;
|
||||
@@ -23,8 +24,8 @@ public class Commanditemname extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
final ItemStack item = user.getBase().getItemInHand();
|
||||
if (MaterialUtil.isAir(item.getType())) {
|
||||
final ItemStack item = Inventories.getItemInHand(user.getBase());
|
||||
if (item == null || MaterialUtil.isAir(item.getType())) {
|
||||
user.sendMessage(tl("itemnameInvalidItem"));
|
||||
return;
|
||||
}
|
||||
@@ -50,8 +51,8 @@ public class Commanditemname extends EssentialsCommand {
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
|
||||
if (args.length == 1) {
|
||||
final ItemStack item = user.getBase().getItemInHand();
|
||||
if (!MaterialUtil.isAir(item.getType()) && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
|
||||
final ItemStack item = Inventories.getItemInHand(user.getBase());
|
||||
if (item != null && !MaterialUtil.isAir(item.getType()) && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
|
||||
return Lists.newArrayList(FormatUtil.unformatString(user, "essentials.itemname", item.getItemMeta().getDisplayName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class Commandkick extends EssentialsCommand {
|
||||
final User user = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : null;
|
||||
|
||||
if (user != null) {
|
||||
if (target.isHidden(sender.getPlayer()) && !user.canInteractVanished() && !sender.getPlayer().canSee(target.getBase())) {
|
||||
if (target.isHidden(sender.getPlayer()) && !user.canInteractVanished() && target.isHiddenFrom(sender.getPlayer())) {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
|
||||
|
||||
@@ -261,8 +261,8 @@ public class Commandmail extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UUID userid : ess.getUserMap().getAllUniqueUsers()) {
|
||||
final User user = ess.getUserMap().getUser(userid);
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user != null) {
|
||||
user.sendMail(messageRecipient, message, dateDiff);
|
||||
}
|
||||
@@ -298,9 +298,21 @@ public class Commandmail extends EssentialsCommand {
|
||||
if (pages == 0) {
|
||||
return Lists.newArrayList("0");
|
||||
} else {
|
||||
final List<String> options = Lists.newArrayList("1");
|
||||
if (pages > 1) {
|
||||
options.add(String.valueOf(pages));
|
||||
final List<String> options = new ArrayList<>();
|
||||
for (int i = 0; i < pages; i++) {
|
||||
options.add(String.valueOf(i + 1));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("clear")) {
|
||||
final ArrayList<MailMessage> mail = user.getMailMessages();
|
||||
// We show up to 9 mails on a page, we don't need to autocomplete more than that...
|
||||
if (mail.size() >= 9) {
|
||||
return Lists.newArrayList("1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
} else {
|
||||
final List<String> options = new ArrayList<>();
|
||||
for (int i = 0; i < mail.size(); i++) {
|
||||
options.add(String.valueOf(i + 1));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.OfflinePlayer;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import net.ess3.api.events.MuteStatusChangeEvent;
|
||||
@@ -29,7 +29,7 @@ public class Commandmute extends EssentialsCommand {
|
||||
user = getPlayer(server, args, 0, true, true);
|
||||
} catch (final PlayerNotFoundException e) {
|
||||
nomatch = true;
|
||||
user = ess.getUser(new OfflinePlayer(args[0], ess.getServer()));
|
||||
user = ess.getUser(new OfflinePlayerStub(args[0], ess.getServer()));
|
||||
}
|
||||
if (!user.getBase().isOnline() && sender.isPlayer()) {
|
||||
if (!sender.isAuthorized("essentials.mute.offline", ess)) {
|
||||
|
||||
@@ -87,7 +87,7 @@ public class Commandnear extends EssentialsCommand {
|
||||
final Queue<User> nearbyPlayers = new PriorityQueue<>((o1, o2) -> (int) (o1.getLocation().distanceSquared(loc) - o2.getLocation().distanceSquared(loc)));
|
||||
|
||||
for (final User player : ess.getOnlineUsers()) {
|
||||
if (!player.equals(user) && !player.isAuthorized("essentials.near.exclude") && (!player.isHidden(user.getBase()) || showHidden || user.getBase().canSee(player.getBase()))) {
|
||||
if (!player.equals(user) && !player.isAuthorized("essentials.near.exclude") && (!player.isHidden(user.getBase()) || showHidden || !player.isHiddenFrom(user.getBase()))) {
|
||||
final Location playerLoc = player.getLocation();
|
||||
if (playerLoc.getWorld() != world) {
|
||||
continue;
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -15,6 +16,9 @@ import java.util.List;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class Commandnuke extends EssentialsCommand {
|
||||
|
||||
public static final String NUKE_META_KEY = "ess_tnt_proj";
|
||||
|
||||
public Commandnuke() {
|
||||
super("nuke");
|
||||
}
|
||||
@@ -30,7 +34,6 @@ public class Commandnuke extends EssentialsCommand {
|
||||
} else {
|
||||
targets = ess.getOnlinePlayers();
|
||||
}
|
||||
ess.getTNTListener().enable();
|
||||
for (final Player player : targets) {
|
||||
if (player == null) {
|
||||
continue;
|
||||
@@ -38,9 +41,12 @@ public class Commandnuke extends EssentialsCommand {
|
||||
player.sendMessage(tl("nuke"));
|
||||
final Location loc = player.getLocation();
|
||||
final World world = loc.getWorld();
|
||||
for (int x = -10; x <= 10; x += 5) {
|
||||
for (int z = -10; z <= 10; z += 5) {
|
||||
world.spawn(new Location(world, loc.getBlockX() + x, world.getHighestBlockYAt(loc) + 64, loc.getBlockZ() + z), TNTPrimed.class);
|
||||
if (world != null) {
|
||||
for (int x = -10; x <= 10; x += 5) {
|
||||
for (int z = -10; z <= 10; z += 5) {
|
||||
final TNTPrimed entity = world.spawn(new Location(world, loc.getBlockX() + x, world.getHighestBlockYAt(loc) + 64, loc.getBlockZ() + z), TNTPrimed.class);
|
||||
entity.setMetadata(NUKE_META_KEY, new FixedMetadataValue(ess, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Material;
|
||||
@@ -22,7 +23,7 @@ public class Commandpowertool extends EssentialsCommand {
|
||||
@Override
|
||||
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
final String command = getFinalArg(args, 0);
|
||||
final ItemStack itemStack = user.getBase().getItemInHand();
|
||||
final ItemStack itemStack = Inventories.getItemInHand(user.getBase());
|
||||
powertool(user.getSource(), user, itemStack, command);
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ public class Commandpowertool extends EssentialsCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
final ItemStack itemStack = user.getBase().getItemInHand();
|
||||
final ItemStack itemStack = Inventories.getItemInHand(user.getBase());
|
||||
final List<String> powertools = user.getPowertool(itemStack);
|
||||
for (final String tool : powertools) {
|
||||
options.add("r:" + tool);
|
||||
|
||||
@@ -25,7 +25,7 @@ public class Commandrealname extends EssentialsCommand {
|
||||
final boolean skipHidden = sender.isPlayer() && !ess.getUser(sender.getPlayer()).canInteractVanished();
|
||||
boolean foundUser = false;
|
||||
for (final User u : ess.getOnlineUsers()) {
|
||||
if (skipHidden && u.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(u.getBase())) {
|
||||
if (skipHidden && u.isHidden(sender.getPlayer()) && u.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
u.setDisplayNick();
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -53,7 +54,18 @@ public class Commandrecipe extends EssentialsCommand {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
final ItemStack itemType = ess.getItemDb().get(args[0]);
|
||||
final ItemStack itemType;
|
||||
|
||||
if (args[0].equalsIgnoreCase("hand")) {
|
||||
if (!sender.isPlayer()) {
|
||||
throw new Exception(tl("consoleCannotUseCommand"));
|
||||
}
|
||||
|
||||
itemType = Inventories.getItemInHand(sender.getPlayer());
|
||||
} else {
|
||||
itemType = ess.getItemDb().get(args[0]);
|
||||
}
|
||||
|
||||
int recipeNo = 0;
|
||||
|
||||
if (args.length > 1) {
|
||||
@@ -155,6 +167,7 @@ public class Commandrecipe extends EssentialsCommand {
|
||||
final List<ItemStack> ingredients = recipe.getIngredientList();
|
||||
if (showWindow) {
|
||||
final User user = ess.getUser(sender.getPlayer());
|
||||
user.getBase().closeInventory();
|
||||
user.setRecipeSee(true);
|
||||
final InventoryView view = user.getBase().openWorkbench(null, true);
|
||||
for (int i = 0; i < ingredients.size(); i++) {
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.api.IUser;
|
||||
import net.essentialsx.api.v2.events.HomeModifyEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class Commandrenamehome extends EssentialsCommand {
|
||||
public Commandrenamehome() {
|
||||
super("renamehome");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
User usersHome = user;
|
||||
final String oldName;
|
||||
final String newName;
|
||||
|
||||
// Allowing both formats /renamehome jroy home1 home | /sethome jroy:home1 home
|
||||
if (args.length == 2) {
|
||||
final String[] nameParts = args[0].split(":", 2);
|
||||
newName = args[1].toLowerCase(Locale.ENGLISH);
|
||||
|
||||
if (nameParts.length == 2) {
|
||||
oldName = nameParts[1].toLowerCase(Locale.ENGLISH);
|
||||
if (user.isAuthorized("essentials.renamehome.others")) {
|
||||
usersHome = getPlayer(server, nameParts[0], true, true);
|
||||
if (usersHome == null) {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
oldName = args[0].toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
} else if (args.length == 3) {
|
||||
if (!user.isAuthorized("essentials.renamehome.others")) {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
usersHome = getPlayer(server, args[0], true, true);
|
||||
if (usersHome == null) {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
|
||||
oldName = args[1].toLowerCase(Locale.ENGLISH);
|
||||
newName = args[2].toLowerCase(Locale.ENGLISH);
|
||||
} else {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
if ("bed".equals(newName) || NumberUtil.isInt(newName) || "bed".equals(oldName) || NumberUtil.isInt(oldName)) {
|
||||
throw new NoSuchFieldException(tl("invalidHomeName"));
|
||||
}
|
||||
|
||||
final HomeModifyEvent event = new HomeModifyEvent(user, usersHome, oldName, newName, usersHome.getHome(oldName));
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("HomeModifyEvent canceled for /renamehome execution by " + user.getDisplayName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
usersHome.renameHome(oldName, newName);
|
||||
user.sendMessage(tl("homeRenamed", oldName, newName));
|
||||
usersHome.setLastHomeConfirmation(null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(final Server server, final CommandSource sender, final String commandLabel, final String[] args) {
|
||||
final IUser user = sender.getUser(ess);
|
||||
if (args.length != 1) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> homes = user == null ? new ArrayList<>() : user.getHomes();
|
||||
final boolean canRenameOthers = sender.isAuthorized("essentials.renamehome.others", ess);
|
||||
|
||||
if (canRenameOthers) {
|
||||
final int sepIndex = args[0].indexOf(':');
|
||||
if (sepIndex < 0) {
|
||||
getPlayers(server, sender).forEach(player -> homes.add(player + ":"));
|
||||
} else {
|
||||
final String namePart = args[0].substring(0, sepIndex);
|
||||
final User otherUser;
|
||||
try {
|
||||
otherUser = getPlayer(server, new String[]{namePart}, 0, true, true);
|
||||
} catch (final Exception ex) {
|
||||
return homes;
|
||||
}
|
||||
otherUser.getHomes().forEach(home -> homes.add(namePart + ":" + home));
|
||||
}
|
||||
}
|
||||
return homes;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.ChargeException;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -62,7 +63,7 @@ public class Commandrepair extends EssentialsCommand {
|
||||
|
||||
public void repairAll(final User user) throws Exception {
|
||||
final List<String> repaired = new ArrayList<>();
|
||||
repairItems(user.getBase().getInventory().getContents(), user, repaired);
|
||||
repairItems(Inventories.getInventory(user.getBase(), false), user, repaired);
|
||||
|
||||
if (user.isAuthorized("essentials.repair.armor")) {
|
||||
repairItems(user.getBase().getInventory().getArmorContents(), user, repaired);
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.UserMap;
|
||||
import com.earth2me.essentials.craftbukkit.BanLookup;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
@@ -63,7 +62,7 @@ public class Commandseen extends EssentialsCommand {
|
||||
ess.getScheduler().runTaskAsynchronously(ess, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final User userFromBukkit = ess.getUserMap().getUserFromBukkit(args[0]);
|
||||
final User userFromBukkit = ess.getUsers().getUser(args[0]);
|
||||
try {
|
||||
if (userFromBukkit != null) {
|
||||
showUserSeen(userFromBukkit);
|
||||
@@ -103,8 +102,8 @@ public class Commandseen extends EssentialsCommand {
|
||||
user.setDisplayNick();
|
||||
sender.sendMessage(tl("seenOnline", user.getDisplayName(), DateUtil.formatDateDiff(user.getLastLogin())));
|
||||
|
||||
final List<String> history = ess.getUserMap().getUserHistory(user.getBase().getUniqueId());
|
||||
if (history != null && history.size() > 1) {
|
||||
final List<String> history = user.getPastUsernames();
|
||||
if (history != null && !history.isEmpty()) {
|
||||
sender.sendMessage(tl("seenAccounts", StringUtil.joinListSkip(", ", user.getName(), history)));
|
||||
}
|
||||
|
||||
@@ -139,7 +138,7 @@ public class Commandseen extends EssentialsCommand {
|
||||
user.setDisplayNick();
|
||||
if (user.getLastLogout() > 0) {
|
||||
sender.sendMessage(tl("seenOffline", user.getName(), DateUtil.formatDateDiff(user.getLastLogout())));
|
||||
final List<String> history = ess.getUserMap().getUserHistory(user.getBase().getUniqueId());
|
||||
final List<String> history = user.getPastUsernames();
|
||||
if (history != null && history.size() > 1) {
|
||||
sender.sendMessage(tl("seenAccounts", StringUtil.joinListSkip(", ", user.getName(), history)));
|
||||
}
|
||||
@@ -192,14 +191,12 @@ public class Commandseen extends EssentialsCommand {
|
||||
}
|
||||
|
||||
private void seenIP(final CommandSource sender, final String ipAddress, final String display) {
|
||||
final UserMap userMap = ess.getUserMap();
|
||||
|
||||
sender.sendMessage(tl("runningPlayerMatch", display));
|
||||
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
final List<String> matches = new ArrayList<>();
|
||||
for (final UUID u : userMap.getAllUniqueUsers()) {
|
||||
final User user = ess.getUserMap().getUser(u);
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.ess3.api.events.UserBalanceUpdateEvent;
|
||||
@@ -108,11 +109,11 @@ public class Commandsell extends EssentialsCommand {
|
||||
//TODO: Prices for Enchantments
|
||||
final ItemStack ris = is.clone();
|
||||
ris.setAmount(amount);
|
||||
if (!user.getBase().getInventory().containsAtLeast(ris, amount)) {
|
||||
if (!Inventories.containsAtLeast(user.getBase(), ris, amount)) {
|
||||
// This should never happen.
|
||||
throw new IllegalStateException("Trying to remove more items than are available.");
|
||||
}
|
||||
user.getBase().getInventory().removeItem(ris);
|
||||
Inventories.removeItemAmount(user.getBase(), ris, ris.getAmount());
|
||||
user.getBase().updateInventory();
|
||||
Trade.log("Command", "Sell", "Item", user.getName(), new Trade(ris, ess), user.getName(), new Trade(result, ess), user.getLocation(), user.getMoney(), ess);
|
||||
user.giveMoney(result, null, UserBalanceUpdateEvent.Cause.COMMAND_SELL);
|
||||
|
||||
@@ -4,6 +4,8 @@ import com.earth2me.essentials.CommandSource;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.essentialsx.api.v2.events.HomeModifyEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
|
||||
@@ -62,8 +64,25 @@ public class Commandsethome extends EssentialsCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
final Location prevHomeLoc = usersHome.getHome(name);
|
||||
|
||||
final HomeModifyEvent event;
|
||||
if (prevHomeLoc == null) {
|
||||
event = new HomeModifyEvent(user, usersHome, name, location, true);
|
||||
} else {
|
||||
event = new HomeModifyEvent(user, usersHome, name, prevHomeLoc, location);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("HomeModifyEvent canceled for /sethome execution by " + user.getDisplayName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
usersHome.setHome(name, location);
|
||||
user.sendMessage(tl("homeSet", user.getLocation().getWorld().getName(), user.getLocation().getBlockX(), user.getLocation().getBlockY(), user.getLocation().getBlockZ(), name));
|
||||
user.sendMessage(tl("homeSet", location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), name));
|
||||
usersHome.setLastHomeConfirmation(null);
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class Commandsetworth extends EssentialsCommand {
|
||||
final ItemStack stack;
|
||||
final String price;
|
||||
if (args.length == 1) {
|
||||
stack = user.getBase().getInventory().getItemInHand();
|
||||
stack = user.getItemInHand();
|
||||
price = args[0];
|
||||
} else {
|
||||
stack = ess.getItemDb().get(args[0]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.InventoryWorkaround;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.EnumUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -9,7 +9,6 @@ import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -60,26 +59,21 @@ public class Commandskull extends EssentialsCommand {
|
||||
}
|
||||
|
||||
private void editSkull(final User user, final ItemStack stack, final SkullMeta skullMeta, final String owner, final boolean spawn) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//Run this stuff async because SkullMeta#setOwner causes a http request.
|
||||
skullMeta.setDisplayName("§fSkull of " + owner);
|
||||
skullMeta.setOwner(owner);
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
stack.setItemMeta(skullMeta);
|
||||
if (spawn) {
|
||||
InventoryWorkaround.addItems(user.getBase().getInventory(), stack);
|
||||
user.sendMessage(tl("givenSkull", owner));
|
||||
return;
|
||||
}
|
||||
user.sendMessage(tl("skullChanged", owner));
|
||||
}
|
||||
}.runTask(ess);
|
||||
}
|
||||
}.runTaskAsynchronously(ess);
|
||||
ess.runTaskAsynchronously(() -> {
|
||||
//Run this stuff async because SkullMeta#setOwner causes a http request.
|
||||
skullMeta.setDisplayName("§fSkull of " + owner);
|
||||
//noinspection deprecation
|
||||
skullMeta.setOwner(owner);
|
||||
ess.scheduleSyncDelayedTask(() -> {
|
||||
stack.setItemMeta(skullMeta);
|
||||
if (spawn) {
|
||||
Inventories.addItem(user.getBase(), stack);
|
||||
user.sendMessage(tl("givenSkull", owner));
|
||||
return;
|
||||
}
|
||||
user.sendMessage(tl("skullChanged", owner));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Commandspeed extends EssentialsCommand {
|
||||
final List<Player> matchedPlayers = server.matchPlayer(name);
|
||||
for (final Player matchPlayer : matchedPlayers) {
|
||||
final User player = ess.getUser(matchPlayer);
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(matchPlayer)) {
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
foundUser = true;
|
||||
|
||||
@@ -24,12 +24,12 @@ public class Commandtop extends EssentialsCommand {
|
||||
final float yaw = user.getLocation().getYaw();
|
||||
final Location unsafe = new Location(user.getWorld(), topX, ess.getWorldInfoProvider().getMaxHeight(user.getWorld()), topZ, yaw, pitch);
|
||||
final Location safe = LocationUtil.getSafeDestination(ess, unsafe);
|
||||
final CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
final CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportTop", safe.getWorld().getName(), safe.getBlockX(), safe.getBlockY(), safe.getBlockZ()));
|
||||
}
|
||||
});
|
||||
user.getAsyncTeleport().teleport(safe, new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
user.getAsyncTeleport().teleport(safe, new Trade(this.getName(), ess), TeleportCause.COMMAND, future);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,11 @@ public class Commandtpoffline extends EssentialsCommand {
|
||||
final User target = getPlayer(server, args, 0, true, true);
|
||||
final Location logout = target.getLogoutLocation();
|
||||
|
||||
if (logout == null) {
|
||||
user.sendMessage(tl("teleportOfflineUnknown", user.getDisplayName()));
|
||||
throw new NoChargeException();
|
||||
}
|
||||
|
||||
if (user.getWorld() != logout.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + logout.getWorld().getName())) {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + logout.getWorld().getName()));
|
||||
}
|
||||
|
||||
@@ -66,9 +66,9 @@ public class Commandtppos extends EssentialsCommand {
|
||||
}
|
||||
|
||||
final User user = getPlayer(server, args, 0, true, false);
|
||||
final double x = args[1].startsWith("~") ? user.getLocation().getX() + (args[1].length() > 1 ? Integer.parseInt(args[1].substring(1)) : 0) : Integer.parseInt(args[1]);
|
||||
final double y = args[2].startsWith("~") ? user.getLocation().getY() + (args[2].length() > 1 ? Integer.parseInt(args[2].substring(1)) : 0) : Integer.parseInt(args[2]);
|
||||
final double z = args[3].startsWith("~") ? user.getLocation().getZ() + (args[3].length() > 1 ? Integer.parseInt(args[3].substring(1)) : 0) : Integer.parseInt(args[3]);
|
||||
final double x = args[1].startsWith("~") ? user.getLocation().getX() + (args[1].length() > 1 ? Double.parseDouble(args[1].substring(1)) : 0) : Double.parseDouble(args[1]);
|
||||
final double y = args[2].startsWith("~") ? user.getLocation().getY() + (args[2].length() > 1 ? Double.parseDouble(args[2].substring(1)) : 0) : Double.parseDouble(args[2]);
|
||||
final double z = args[3].startsWith("~") ? user.getLocation().getZ() + (args[3].length() > 1 ? Double.parseDouble(args[3].substring(1)) : 0) : Double.parseDouble(args[3]);
|
||||
final Location loc = new Location(user.getWorld(), x, y, z, user.getLocation().getYaw(), user.getLocation().getPitch());
|
||||
if (args.length == 5) {
|
||||
loc.setWorld(ess.getWorld(args[4]));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -75,8 +76,8 @@ public class Commandunlimited extends EssentialsCommand {
|
||||
if (!target.hasUnlimited(stack)) {
|
||||
message = "enableUnlimited";
|
||||
enableUnlimited = true;
|
||||
if (!target.getBase().getInventory().containsAtLeast(stack, stack.getAmount())) {
|
||||
target.getBase().getInventory().addItem(stack);
|
||||
if (!Inventories.containsAtLeast(target.getBase(), stack, stack.getAmount())) {
|
||||
Inventories.addItem(target.getBase(), stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class Commandwhois extends EssentialsCommand {
|
||||
sender.sendMessage(tl("whoisHunger", user.getBase().getFoodLevel(), user.getBase().getSaturation()));
|
||||
sender.sendMessage(tl("whoisExp", SetExpFix.getTotalExperience(user.getBase()), user.getBase().getLevel()));
|
||||
sender.sendMessage(tl("whoisLocation", user.getLocation().getWorld().getName(), user.getLocation().getBlockX(), user.getLocation().getBlockY(), user.getLocation().getBlockZ()));
|
||||
final long playtimeMs = System.currentTimeMillis() - (user.getBase().getStatistic(PLAY_ONE_TICK) * 50);
|
||||
final long playtimeMs = System.currentTimeMillis() - (user.getBase().getStatistic(PLAY_ONE_TICK) * 50L);
|
||||
sender.sendMessage(tl("whoisPlaytime", DateUtil.formatDateDiff(playtimeMs)));
|
||||
if (!ess.getSettings().isEcoDisabled()) {
|
||||
sender.sendMessage(tl("whoisMoney", NumberUtil.displayCurrency(user.getMoney(), ess)));
|
||||
|
||||
+12
-7
@@ -30,16 +30,21 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
|
||||
final UUID uuid = StringUtil.toUUID(searchTerm);
|
||||
if (uuid != null) {
|
||||
final User matchedUser = ess.getUser(uuid);
|
||||
if (matchedUser == null) {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
userConsumer.accept(matchedUser);
|
||||
} else if (matchWildcards && searchTerm.contentEquals("**")) {
|
||||
for (final UUID sUser : ess.getUserMap().getAllUniqueUsers()) {
|
||||
final User matchedUser = ess.getUser(sUser);
|
||||
userConsumer.accept(matchedUser);
|
||||
for (final UUID u : ess.getUsers().getAllUserUUIDs()) {
|
||||
final User user = ess.getUsers().loadUncachedUser(u);
|
||||
if (user != null) {
|
||||
userConsumer.accept(user);
|
||||
}
|
||||
}
|
||||
} else if (matchWildcards && searchTerm.contentEquals("*")) {
|
||||
final boolean skipHidden = sender.isPlayer() && !ess.getUser(sender.getPlayer()).canInteractVanished();
|
||||
for (final User onlineUser : ess.getOnlineUsers()) {
|
||||
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(onlineUser.getBase())) {
|
||||
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && onlineUser.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
userConsumer.accept(onlineUser);
|
||||
@@ -76,7 +81,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
|
||||
|
||||
if (matchWildcards && (searchTerm.contentEquals("**") || searchTerm.contentEquals("*"))) {
|
||||
for (final User onlineUser : ess.getOnlineUsers()) {
|
||||
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(onlineUser.getBase())) {
|
||||
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && onlineUser.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
userConsumer.accept(onlineUser);
|
||||
@@ -91,7 +96,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
|
||||
if (matchedPlayers.isEmpty()) {
|
||||
final String matchText = searchTerm.toLowerCase(Locale.ENGLISH);
|
||||
for (final User player : ess.getOnlineUsers()) {
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(player.getBase())) {
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
final String displayName = FormatUtil.stripFormat(player.getDisplayName()).toLowerCase(Locale.ENGLISH);
|
||||
@@ -103,7 +108,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
|
||||
} else {
|
||||
for (final Player matchPlayer : matchedPlayers) {
|
||||
final User player = ess.getUser(matchPlayer);
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(matchPlayer)) {
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
foundUser = true;
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ public abstract class EssentialsToggleCommand extends EssentialsCommand {
|
||||
final List<Player> matchedPlayers = server.matchPlayer(args[0]);
|
||||
for (final Player matchPlayer : matchedPlayers) {
|
||||
final User player = ess.getUser(matchPlayer);
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(matchPlayer)) {
|
||||
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
|
||||
continue;
|
||||
}
|
||||
foundUser = true;
|
||||
|
||||
+33
-3
@@ -33,7 +33,9 @@ import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -103,6 +105,15 @@ public class EssentialsConfiguration {
|
||||
return configurationNode;
|
||||
}
|
||||
|
||||
public void setRootHolder(final Class<?> holderClass, final Object holder) {
|
||||
try {
|
||||
getRootNode().set(holderClass, holder);
|
||||
} catch (SerializationException e) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, "Error while saving user config: " + configFile.getName(), e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return configFile;
|
||||
}
|
||||
@@ -120,6 +131,7 @@ public class EssentialsConfiguration {
|
||||
try {
|
||||
return node.get(LazyLocation.class);
|
||||
} catch (SerializationException e) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -261,7 +273,8 @@ public class EssentialsConfiguration {
|
||||
try {
|
||||
return node.get(BigDecimal.class);
|
||||
} catch (SerializationException e) {
|
||||
return null;
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +307,19 @@ public class EssentialsConfiguration {
|
||||
return ConfigurateUtil.getMap(configurationNode);
|
||||
}
|
||||
|
||||
public Map<String, String> getStringMap(String path) {
|
||||
final CommentedConfigurationNode node = getInternal(path);
|
||||
if (node == null || !node.isMap()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final Map<String, String> map = new LinkedHashMap<>();
|
||||
for (Map.Entry<Object, CommentedConfigurationNode> entry : node.childrenMap().entrySet()) {
|
||||
map.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue().rawScalar()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public void removeProperty(String path) {
|
||||
final CommentedConfigurationNode node = getInternal(path);
|
||||
if (node != null) {
|
||||
@@ -366,10 +392,10 @@ public class EssentialsConfiguration {
|
||||
} catch (final ParsingException e) {
|
||||
final File broken = new File(configFile.getAbsolutePath() + ".broken." + System.currentTimeMillis());
|
||||
if (configFile.renameTo(broken)) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, "The file " + configFile.toString() + " is broken, it has been renamed to " + broken.toString(), e.getCause());
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, "The file " + configFile + " is broken, it has been renamed to " + broken, e.getCause());
|
||||
return;
|
||||
}
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, "The file " + configFile.toString() + " is broken. A backup file has failed to be created", e.getCause());
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, "The file " + configFile + " is broken. A backup file has failed to be created", e.getCause());
|
||||
} catch (final ConfigurateException e) {
|
||||
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
} finally {
|
||||
@@ -420,6 +446,10 @@ public class EssentialsConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTransaction() {
|
||||
return transaction.get();
|
||||
}
|
||||
|
||||
public void setSaveHook(Runnable saveHook) {
|
||||
this.saveHook = saveHook;
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class EssentialsUserConfiguration extends EssentialsConfiguration {
|
||||
|
||||
private File getAltFile() {
|
||||
final UUID fn = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username.toLowerCase(Locale.ENGLISH)).getBytes(Charsets.UTF_8));
|
||||
return new File(configFile.getParentFile(), fn.toString() + ".yml");
|
||||
return new File(configFile.getParentFile(), fn + ".yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -262,6 +262,16 @@ public class UserConfigHolder {
|
||||
this.lastAccountName = value;
|
||||
}
|
||||
|
||||
private @MonotonicNonNull String npcName;
|
||||
|
||||
public String npcName() {
|
||||
return this.npcName;
|
||||
}
|
||||
|
||||
public void npcName(final String value) {
|
||||
this.npcName = value;
|
||||
}
|
||||
|
||||
private boolean powertoolsenabled = true;
|
||||
|
||||
public boolean powerToolsEnabled() {
|
||||
@@ -332,6 +342,20 @@ public class UserConfigHolder {
|
||||
this.shouting = value;
|
||||
}
|
||||
|
||||
@DeleteOnEmpty
|
||||
private @MonotonicNonNull List<String> pastUsernames;
|
||||
|
||||
public List<String> pastUsernames() {
|
||||
if (this.pastUsernames == null) {
|
||||
this.pastUsernames = new ArrayList<>();
|
||||
}
|
||||
return this.pastUsernames;
|
||||
}
|
||||
|
||||
public void pastUsernames(List<String> value) {
|
||||
this.pastUsernames = value;
|
||||
}
|
||||
|
||||
private @NonNull Timestamps timestamps = new Timestamps();
|
||||
|
||||
public Timestamps timestamps() {
|
||||
|
||||
+3
-1
@@ -17,7 +17,9 @@ public class MaterialTypeSerializer extends ScalarSerializer<Material> {
|
||||
if (obj instanceof String) {
|
||||
return Material.matchMaterial((String) obj);
|
||||
}
|
||||
return null;
|
||||
|
||||
// Configurate will use an EnumSet to deserialize, which doesn't support null types. Default to air.
|
||||
return Material.AIR;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,8 +21,9 @@ public final class BanLookup {
|
||||
}
|
||||
|
||||
public static BanEntry getBanEntry(final IEssentials ess, final String name) {
|
||||
final Set<BanEntry> benteries = ess.getServer().getBanList(BanList.Type.NAME).getBanEntries();
|
||||
for (final BanEntry banEnt : benteries) {
|
||||
final Set benteries = ess.getServer().getBanList(BanList.Type.NAME).getBanEntries();
|
||||
for (final Object ob : benteries) {
|
||||
final BanEntry banEnt = (BanEntry) ob;
|
||||
if (banEnt.getTarget().equals(name)) {
|
||||
return banEnt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
package com.earth2me.essentials.craftbukkit;
|
||||
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class Inventories {
|
||||
private static final int HELM_SLOT = 39;
|
||||
private static final int CHEST_SLOT = 38;
|
||||
private static final int LEG_SLOT = 37;
|
||||
private static final int BOOT_SLOT = 36;
|
||||
private static final boolean HAS_OFFHAND = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01);
|
||||
private static final int INVENTORY_SIZE = HAS_OFFHAND ? 41 : 40;
|
||||
|
||||
private Inventories() {
|
||||
}
|
||||
|
||||
public static ItemStack getItemInHand(final Player player) {
|
||||
if (!HAS_OFFHAND) {
|
||||
//noinspection deprecation
|
||||
return player.getInventory().getItemInHand();
|
||||
}
|
||||
final PlayerInventory inventory = player.getInventory();
|
||||
final ItemStack main = inventory.getItemInMainHand();
|
||||
return !isEmpty(main) ? main : inventory.getItemInOffHand();
|
||||
}
|
||||
|
||||
public static ItemStack getItemInMainHand(final Player player) {
|
||||
if (!HAS_OFFHAND) {
|
||||
//noinspection deprecation
|
||||
return player.getInventory().getItemInHand();
|
||||
}
|
||||
return player.getInventory().getItemInMainHand();
|
||||
}
|
||||
|
||||
public static void setItemInMainHand(final Player player, final ItemStack stack) {
|
||||
if (HAS_OFFHAND) {
|
||||
player.getInventory().setItemInMainHand(stack);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
player.setItemInHand(stack);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setItemInMainHand(final EntityEquipment entityEquipment, final ItemStack stack) {
|
||||
if (HAS_OFFHAND) {
|
||||
entityEquipment.setItemInMainHand(stack);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
entityEquipment.setItemInHand(stack);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setItemInMainHandDropChance(final EntityEquipment entityEquipment, final float chance) {
|
||||
if (HAS_OFFHAND) {
|
||||
entityEquipment.setItemInMainHandDropChance(chance);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
entityEquipment.setItemInHandDropChance(chance);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsAtLeast(final Player player, final ItemStack item, int amount) {
|
||||
for (final ItemStack invItem : player.getInventory().getContents()) {
|
||||
if (isEmpty(invItem)) {
|
||||
continue;
|
||||
}
|
||||
if (invItem.isSimilar(item)) {
|
||||
amount -= invItem.getAmount();
|
||||
if (amount <= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasSpace(final Player player, final int maxStack, final boolean includeArmor, ItemStack... items) {
|
||||
items = normalizeItems(cloneItems(items));
|
||||
final InventoryData inventoryData = parseInventoryData(player.getInventory(), items, maxStack, includeArmor);
|
||||
|
||||
final List<Integer> emptySlots = inventoryData.getEmptySlots();
|
||||
for (final ItemStack item : items) {
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int itemMax = Math.max(maxStack, item.getMaxStackSize());
|
||||
final List<Integer> partialSlots = inventoryData.getPartialSlots().get(item);
|
||||
while (true) {
|
||||
if (partialSlots == null || partialSlots.isEmpty()) {
|
||||
if (emptySlots.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
emptySlots.remove(0);
|
||||
if (item.getAmount() > itemMax) {
|
||||
item.setAmount(item.getAmount() - itemMax);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
final int slot = partialSlots.remove(0);
|
||||
ItemStack existing = player.getInventory().getItem(slot);
|
||||
if (isEmpty(existing)) {
|
||||
existing = item.clone();
|
||||
existing.setAmount(0);
|
||||
}
|
||||
|
||||
final int amount = item.getAmount();
|
||||
final int existingAmount = existing.getAmount();
|
||||
|
||||
if (amount + existingAmount <= itemMax) {
|
||||
break;
|
||||
} else {
|
||||
item.setAmount(amount + existingAmount - itemMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Map<Integer, ItemStack> addItem(final Player player, final ItemStack... items) {
|
||||
return addItem(player, 0, false, items);
|
||||
}
|
||||
|
||||
public static Map<Integer, ItemStack> addItem(final Player player, final int maxStack, final ItemStack... items) {
|
||||
return addItem(player, maxStack, false, items);
|
||||
}
|
||||
|
||||
public static Map<Integer, ItemStack> addItem(final Player player, final int maxStack, final boolean allowArmor, ItemStack... items) {
|
||||
items = normalizeItems(cloneItems(items));
|
||||
final Map<Integer, ItemStack> leftover = new HashMap<>();
|
||||
final InventoryData inventoryData = parseInventoryData(player.getInventory(), items, maxStack, allowArmor);
|
||||
|
||||
final List<Integer> emptySlots = inventoryData.getEmptySlots();
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
final ItemStack item = items[i];
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int itemMax = Math.max(maxStack, item.getMaxStackSize());
|
||||
final List<Integer> partialSlots = inventoryData.getPartialSlots().get(item);
|
||||
while (true) {
|
||||
if (partialSlots == null || partialSlots.isEmpty()) {
|
||||
if (emptySlots.isEmpty()) {
|
||||
leftover.put(i, item);
|
||||
break;
|
||||
}
|
||||
|
||||
final int slot = emptySlots.remove(0);
|
||||
if (item.getAmount() > itemMax) {
|
||||
final ItemStack split = item.clone();
|
||||
split.setAmount(itemMax);
|
||||
player.getInventory().setItem(slot, split);
|
||||
item.setAmount(item.getAmount() - itemMax);
|
||||
} else {
|
||||
player.getInventory().setItem(slot, item);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
final int slot = partialSlots.remove(0);
|
||||
ItemStack existing = player.getInventory().getItem(slot);
|
||||
if (isEmpty(existing)) {
|
||||
existing = item.clone();
|
||||
existing.setAmount(0);
|
||||
}
|
||||
|
||||
final int amount = item.getAmount();
|
||||
final int existingAmount = existing.getAmount();
|
||||
|
||||
if (amount + existingAmount <= itemMax) {
|
||||
existing.setAmount(amount + existingAmount);
|
||||
player.getInventory().setItem(slot, existing);
|
||||
break;
|
||||
} else {
|
||||
existing.setAmount(itemMax);
|
||||
player.getInventory().setItem(slot, existing);
|
||||
item.setAmount(amount + existingAmount - itemMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return leftover;
|
||||
}
|
||||
|
||||
public static ItemStack[] getInventory(final Player player, final boolean includeArmor) {
|
||||
final ItemStack[] items = new ItemStack[INVENTORY_SIZE];
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
if (!includeArmor && isArmorSlot(i)) {
|
||||
items[i] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
items[i] = player.getInventory().getItem(i);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public static void removeItemExact(final Player player, final ItemStack toRemove, final boolean includeArmor) {
|
||||
removeItems(player, itemStack -> itemStack.equals(toRemove), includeArmor);
|
||||
}
|
||||
|
||||
public static int removeItemSimilar(final Player player, final ItemStack toRemove, final boolean includeArmor) {
|
||||
return removeItems(player, itemStack -> itemStack.isSimilar(toRemove), includeArmor);
|
||||
}
|
||||
|
||||
public static int removeItems(final Player player, final Predicate<ItemStack> removePredicate, final boolean includeArmor) {
|
||||
int removedAmount = 0;
|
||||
final ItemStack[] items = player.getInventory().getContents();
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
if (!includeArmor && isArmorSlot(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final ItemStack item = items[i];
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (removePredicate.test(item)) {
|
||||
removedAmount += item.getAmount();
|
||||
item.setAmount(0);
|
||||
player.getInventory().setItem(i, item);
|
||||
}
|
||||
}
|
||||
return removedAmount;
|
||||
}
|
||||
|
||||
public static boolean removeItemAmount(final Player player, final ItemStack toRemove, int amount) {
|
||||
final List<Integer> clearSlots = new ArrayList<>();
|
||||
final ItemStack[] items = player.getInventory().getContents();
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
final ItemStack item = items[i];
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.isSimilar(toRemove)) {
|
||||
if (item.getAmount() >= amount) {
|
||||
item.setAmount(item.getAmount() - amount);
|
||||
player.getInventory().setItem(i, item);
|
||||
for (final int slot : clearSlots) {
|
||||
clearSlot(player, slot);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
amount -= item.getAmount();
|
||||
clearSlots.add(i);
|
||||
}
|
||||
|
||||
if (amount == 0) {
|
||||
for (final int slot : clearSlots) {
|
||||
clearSlot(player, slot);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void clearSlot(final Player player, final int slot) {
|
||||
final ItemStack item = player.getInventory().getItem(slot);
|
||||
if (!isEmpty(item)) {
|
||||
item.setAmount(0);
|
||||
player.getInventory().setItem(slot, item);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setSlot(final Player inventory, final int slot, final ItemStack item) {
|
||||
inventory.getInventory().setItem(slot, item);
|
||||
}
|
||||
|
||||
private static ItemStack[] normalizeItems(final ItemStack[] items) {
|
||||
if (items.length <= 1) {
|
||||
return items;
|
||||
}
|
||||
|
||||
final ItemStack[] normalizedItems = new ItemStack[items.length];
|
||||
int nextNormalizedIndex = 0;
|
||||
inputLoop:
|
||||
for (final ItemStack item : items) {
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < nextNormalizedIndex; j++) {
|
||||
final ItemStack normalizedItem = normalizedItems[j];
|
||||
if (isEmpty(normalizedItem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.isSimilar(normalizedItem)) {
|
||||
normalizedItem.setAmount(normalizedItem.getAmount() + item.getAmount());
|
||||
continue inputLoop;
|
||||
}
|
||||
}
|
||||
normalizedItems[nextNormalizedIndex++] = item;
|
||||
}
|
||||
|
||||
return normalizedItems;
|
||||
}
|
||||
|
||||
private static ItemStack[] cloneItems(final ItemStack[] items) {
|
||||
final ItemStack[] clonedItems = new ItemStack[items.length];
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
final ItemStack item = items[i];
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clonedItems[i] = item.clone();
|
||||
}
|
||||
|
||||
return clonedItems;
|
||||
}
|
||||
|
||||
private static InventoryData parseInventoryData(final Inventory inventory, final ItemStack[] items, final int maxStack, final boolean includeArmor) {
|
||||
final ItemStack[] inventoryContents = inventory.getContents();
|
||||
final List<Integer> emptySlots = new ArrayList<>();
|
||||
final HashMap<ItemStack, List<Integer>> partialSlots = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < inventoryContents.length; i++) {
|
||||
if (!includeArmor && isArmorSlot(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final ItemStack invItem = inventoryContents[i];
|
||||
if (isEmpty(invItem)) {
|
||||
emptySlots.add(i);
|
||||
} else {
|
||||
for (final ItemStack newItem : items) {
|
||||
if (invItem.getAmount() < Math.max(maxStack, invItem.getMaxStackSize()) && invItem.isSimilar(newItem)) {
|
||||
partialSlots.computeIfAbsent(newItem, k -> new ArrayList<>()).add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert empty armor slots to partial slots if we have armor items in the inventory, otherwise remove them from the empty slots.
|
||||
if (includeArmor) {
|
||||
ItemStack helm = null;
|
||||
ItemStack chest = null;
|
||||
ItemStack legs = null;
|
||||
ItemStack boots = null;
|
||||
for (final ItemStack item : items) {
|
||||
if (isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
if (helm == null && MaterialUtil.isHelmet(item.getType())) {
|
||||
helm = item;
|
||||
if (emptySlots.contains(HELM_SLOT)) {
|
||||
partialSlots.computeIfAbsent(helm, k -> new ArrayList<>()).add(HELM_SLOT);
|
||||
}
|
||||
} else if (chest == null && MaterialUtil.isChestplate(item.getType())) {
|
||||
chest = item;
|
||||
if (emptySlots.contains(CHEST_SLOT)) {
|
||||
partialSlots.computeIfAbsent(chest, k -> new ArrayList<>()).add(CHEST_SLOT);
|
||||
}
|
||||
} else if (legs == null && MaterialUtil.isLeggings(item.getType())) {
|
||||
legs = item;
|
||||
if (emptySlots.contains(LEG_SLOT)) {
|
||||
partialSlots.computeIfAbsent(legs, k -> new ArrayList<>()).add(LEG_SLOT);
|
||||
}
|
||||
} else if (boots == null && MaterialUtil.isBoots(item.getType())) {
|
||||
boots = item;
|
||||
if (emptySlots.contains(BOOT_SLOT)) {
|
||||
partialSlots.computeIfAbsent(boots, k -> new ArrayList<>()).add(BOOT_SLOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
emptySlots.remove((Object) HELM_SLOT);
|
||||
emptySlots.remove((Object) CHEST_SLOT);
|
||||
emptySlots.remove((Object) LEG_SLOT);
|
||||
emptySlots.remove((Object) BOOT_SLOT);
|
||||
}
|
||||
|
||||
return new InventoryData(emptySlots, partialSlots);
|
||||
}
|
||||
|
||||
private static boolean isEmpty(final ItemStack stack) {
|
||||
return stack == null || MaterialUtil.isAir(stack.getType());
|
||||
}
|
||||
|
||||
private static boolean isArmorSlot(final int slot) {
|
||||
return slot == HELM_SLOT || slot == CHEST_SLOT || slot == LEG_SLOT || slot == BOOT_SLOT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.earth2me.essentials.craftbukkit;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class InventoryData {
|
||||
private final List<Integer> emptySlots;
|
||||
private final HashMap<ItemStack, List<Integer>> partialSlots;
|
||||
|
||||
public InventoryData(List<Integer> emptySlots, HashMap<ItemStack, List<Integer>> partialSlots) {
|
||||
this.emptySlots = emptySlots;
|
||||
this.partialSlots = partialSlots;
|
||||
}
|
||||
|
||||
public List<Integer> getEmptySlots() {
|
||||
return emptySlots;
|
||||
}
|
||||
|
||||
public HashMap<ItemStack, List<Integer>> getPartialSlots() {
|
||||
return partialSlots;
|
||||
}
|
||||
}
|
||||
-245
@@ -1,245 +0,0 @@
|
||||
package com.earth2me.essentials.craftbukkit;
|
||||
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* This class can be removed when https://github.com/Bukkit/CraftBukkit/pull/193 is accepted to CraftBukkit
|
||||
*/
|
||||
public final class InventoryWorkaround {
|
||||
/*
|
||||
Spigot 1.9, for whatever reason, decided to merge the armor and main player inventories without providing a way
|
||||
to access the main inventory. There's lots of ugly code in here to work around that.
|
||||
*/
|
||||
private static final int USABLE_PLAYER_INV_SIZE = 36;
|
||||
private static final boolean IS_OFFHAND = VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_9_R01);
|
||||
|
||||
private InventoryWorkaround() {
|
||||
}
|
||||
|
||||
private static int firstPartial(final Inventory inventory, final ItemStack item, final int maxAmount) {
|
||||
if (item == null) {
|
||||
return -1;
|
||||
}
|
||||
final ItemStack[] stacks = inventory.getContents();
|
||||
for (int i = 0; i < stacks.length; i++) {
|
||||
final ItemStack cItem = stacks[i];
|
||||
if (cItem != null && cItem.getAmount() < maxAmount && cItem.isSimilar(item)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static boolean isCombinedInventory(final Inventory inventory) {
|
||||
return inventory instanceof PlayerInventory && inventory.getContents().length > USABLE_PLAYER_INV_SIZE;
|
||||
}
|
||||
|
||||
// Clears inventory without clearing armor
|
||||
public static void clearInventoryNoArmor(final PlayerInventory inventory) {
|
||||
if (isCombinedInventory(inventory)) {
|
||||
for (int i = 0; i < USABLE_PLAYER_INV_SIZE; i++) {
|
||||
inventory.setItem(i, null);
|
||||
}
|
||||
} else {
|
||||
inventory.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static Inventory makeTruncatedPlayerInventory(final PlayerInventory playerInventory) {
|
||||
final Inventory fakeInventory = Bukkit.getServer().createInventory(null, USABLE_PLAYER_INV_SIZE);
|
||||
fakeInventory.setContents(Arrays.copyOf(playerInventory.getContents(), fakeInventory.getSize()));
|
||||
return fakeInventory;
|
||||
}
|
||||
|
||||
// Returns what it couldn't store
|
||||
// This will will abort if it couldn't store all items
|
||||
public static Map<Integer, ItemStack> addAllItems(final Inventory inventory, final ItemStack... items) {
|
||||
final ItemStack[] contents = inventory.getContents();
|
||||
|
||||
final Inventory fakeInventory;
|
||||
if (isCombinedInventory(inventory)) {
|
||||
fakeInventory = makeTruncatedPlayerInventory((PlayerInventory) inventory);
|
||||
} else {
|
||||
fakeInventory = Bukkit.getServer().createInventory(null, inventory.getType());
|
||||
fakeInventory.setContents(contents);
|
||||
}
|
||||
final Map<Integer, ItemStack> overflow = addItems(fakeInventory, items);
|
||||
if (overflow.isEmpty()) {
|
||||
addItems(inventory, items);
|
||||
return null;
|
||||
}
|
||||
return addItems(fakeInventory, items);
|
||||
}
|
||||
|
||||
public static Map<Integer, ItemStack> addAllOversizedItems(final Inventory inventory, final int oversizedStacks, final ItemStack... items) {
|
||||
final ItemStack[] contents = inventory.getContents();
|
||||
|
||||
final Inventory fakeInventory;
|
||||
if (isCombinedInventory(inventory)) {
|
||||
fakeInventory = makeTruncatedPlayerInventory((PlayerInventory) inventory);
|
||||
} else {
|
||||
fakeInventory = Bukkit.getServer().createInventory(null, inventory.getType());
|
||||
fakeInventory.setContents(contents);
|
||||
}
|
||||
final Map<Integer, ItemStack> overflow = addOversizedItems(fakeInventory, oversizedStacks, items);
|
||||
if (overflow.isEmpty()) {
|
||||
addOversizedItems(inventory, oversizedStacks, items);
|
||||
return null;
|
||||
}
|
||||
return overflow;
|
||||
}
|
||||
|
||||
// Returns what it couldn't store
|
||||
public static Map<Integer, ItemStack> addItems(final Inventory inventory, final ItemStack... items) {
|
||||
return addOversizedItems(inventory, 0, items);
|
||||
}
|
||||
|
||||
// Returns what it couldn't store
|
||||
// Set oversizedStack to below normal stack size to disable oversized stacks
|
||||
public static Map<Integer, ItemStack> addOversizedItems(final Inventory inventory, final int oversizedStacks, final ItemStack... items) {
|
||||
if (isCombinedInventory(inventory)) {
|
||||
final Inventory fakeInventory = makeTruncatedPlayerInventory((PlayerInventory) inventory);
|
||||
final Map<Integer, ItemStack> overflow = addOversizedItems(fakeInventory, oversizedStacks, items);
|
||||
for (int i = 0; i < fakeInventory.getContents().length; i++) {
|
||||
inventory.setItem(i, fakeInventory.getContents()[i]);
|
||||
}
|
||||
return overflow;
|
||||
}
|
||||
|
||||
final Map<Integer, ItemStack> leftover = new HashMap<>();
|
||||
|
||||
/*
|
||||
* TODO: some optimization - Create a 'firstPartial' with a 'fromIndex' - Record the lastPartial per Material -
|
||||
* Cache firstEmpty result
|
||||
*/
|
||||
|
||||
// combine items
|
||||
|
||||
final ItemStack[] combined = new ItemStack[items.length];
|
||||
for (final ItemStack item : items) {
|
||||
if (item == null || item.getAmount() < 1) {
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < combined.length; j++) {
|
||||
if (combined[j] == null) {
|
||||
combined[j] = item.clone();
|
||||
break;
|
||||
}
|
||||
if (combined[j].isSimilar(item)) {
|
||||
combined[j].setAmount(combined[j].getAmount() + item.getAmount());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < combined.length; i++) {
|
||||
final ItemStack item = combined[i];
|
||||
if (item == null || item.getType() == Material.AIR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// Do we already have a stack of it?
|
||||
final int maxAmount = Math.max(oversizedStacks, item.getType().getMaxStackSize());
|
||||
final int firstPartial = firstPartial(inventory, item, maxAmount);
|
||||
|
||||
// Drat! no partial stack
|
||||
if (firstPartial == -1) {
|
||||
// Find a free spot!
|
||||
final int firstFree = inventory.firstEmpty();
|
||||
|
||||
if (firstFree == -1) {
|
||||
// No space at all!
|
||||
leftover.put(i, item);
|
||||
break;
|
||||
} else {
|
||||
// More than a single stack!
|
||||
if (item.getAmount() > maxAmount) {
|
||||
final ItemStack stack = item.clone();
|
||||
stack.setAmount(maxAmount);
|
||||
inventory.setItem(firstFree, stack);
|
||||
item.setAmount(item.getAmount() - maxAmount);
|
||||
} else {
|
||||
// Just store it
|
||||
inventory.setItem(firstFree, item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// So, apparently it might only partially fit, well lets do just that
|
||||
final ItemStack partialItem = inventory.getItem(firstPartial);
|
||||
|
||||
final int amount = item.getAmount();
|
||||
final int partialAmount = partialItem.getAmount();
|
||||
|
||||
// Check if it fully fits
|
||||
if (amount + partialAmount <= maxAmount) {
|
||||
partialItem.setAmount(amount + partialAmount);
|
||||
break;
|
||||
}
|
||||
|
||||
// It fits partially
|
||||
partialItem.setAmount(maxAmount);
|
||||
item.setAmount(amount + partialAmount - maxAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return leftover;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void setItemInMainHand(final Player p, final ItemStack item) {
|
||||
if (IS_OFFHAND) {
|
||||
p.getInventory().setItemInMainHand(item);
|
||||
} else {
|
||||
p.setItemInHand(item);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void setItemInMainHand(final EntityEquipment invent, final ItemStack item) {
|
||||
if (IS_OFFHAND) {
|
||||
invent.setItemInMainHand(item);
|
||||
} else {
|
||||
invent.setItemInHand(item);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void setItemInMainHandDropChance(final EntityEquipment invent, final float chance) {
|
||||
if (IS_OFFHAND) {
|
||||
invent.setItemInMainHandDropChance(chance);
|
||||
} else {
|
||||
invent.setItemInHandDropChance(chance);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setItemInOffHand(final Player p, final ItemStack item) {
|
||||
if (IS_OFFHAND) {
|
||||
p.getInventory().setItemInOffHand(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static int clearItemInOffHand(final Player p, final ItemStack item) {
|
||||
if (IS_OFFHAND) {
|
||||
int removedAmount = 0;
|
||||
if (p.getInventory().getItemInOffHand().getType().equals(item.getType())) {
|
||||
removedAmount = p.getInventory().getItemInOffHand().getAmount();
|
||||
p.getInventory().setItemInOffHand(null);
|
||||
}
|
||||
return removedAmount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+18
-10
@@ -1,6 +1,7 @@
|
||||
package com.earth2me.essentials.economy.vault;
|
||||
|
||||
import com.earth2me.essentials.Essentials;
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.api.NoLoanPermittedException;
|
||||
import com.earth2me.essentials.api.UserDoesNotExistException;
|
||||
import com.earth2me.essentials.config.EssentialsUserConfiguration;
|
||||
@@ -11,6 +12,7 @@ import net.ess3.api.MaxMoneyException;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import net.milkbowl.vault.economy.EconomyResponse;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
@@ -308,21 +310,27 @@ public class VaultEconomyProvider implements Economy {
|
||||
npcConfig.setProperty("last-account-name", player.getName());
|
||||
npcConfig.setProperty("money", ess.getSettings().getStartingBalance());
|
||||
npcConfig.blockingSave();
|
||||
ess.getUserMap().trackUUID(player.getUniqueId(), player.getName(), false);
|
||||
// This will load the NPC into the UserMap + UUID cache
|
||||
ess.getUsers().addCachedNpcName(player.getUniqueId(), player.getName());
|
||||
ess.getUsers().getUser(player.getUniqueId());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Loading a v4 UUID that we somehow didn't track, mark it as a normal player and hope for the best, vault sucks :/
|
||||
try {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Vault requested a player account creation for a v4 UUID: " + player);
|
||||
}
|
||||
ess.getUserMap().load(player);
|
||||
return true;
|
||||
} catch (UserDoesNotExistException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Vault requested a player account creation for a v4 UUID: " + player);
|
||||
}
|
||||
|
||||
final Player userPlayer;
|
||||
if (player instanceof Player) {
|
||||
userPlayer = (Player) player;
|
||||
} else {
|
||||
final OfflinePlayerStub essPlayer = new OfflinePlayerStub(player.getUniqueId(), ess.getServer());
|
||||
essPlayer.setName(player.getName());
|
||||
userPlayer = essPlayer;
|
||||
}
|
||||
ess.getUsers().getUser(userPlayer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.earth2me.essentials.items;
|
||||
|
||||
import com.earth2me.essentials.IConf;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
@@ -156,14 +157,14 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
|
||||
} else if (args[0].equalsIgnoreCase("hand")) {
|
||||
is.add(user.getItemInHand().clone());
|
||||
} else if (args[0].equalsIgnoreCase("inventory") || args[0].equalsIgnoreCase("invent") || args[0].equalsIgnoreCase("all")) {
|
||||
for (final ItemStack stack : user.getBase().getInventory().getContents()) {
|
||||
for (final ItemStack stack : Inventories.getInventory(user.getBase(), true)) {
|
||||
if (stack == null || stack.getType() == Material.AIR) {
|
||||
continue;
|
||||
}
|
||||
is.add(stack.clone());
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("blocks")) {
|
||||
for (final ItemStack stack : user.getBase().getInventory().getContents()) {
|
||||
for (final ItemStack stack : Inventories.getInventory(user.getBase(), true)) {
|
||||
if (stack == null || stack.getType() == Material.AIR || !stack.getType().isBlock()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.earth2me.essentials.perm;
|
||||
import com.earth2me.essentials.Essentials;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.TriState;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
@@ -10,9 +11,15 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface IPermissionsHandler {
|
||||
String getGroup(Player base);
|
||||
boolean addToGroup(OfflinePlayer base, String group);
|
||||
|
||||
List<String> getGroups(Player base);
|
||||
boolean removeFromGroup(OfflinePlayer base, String group);
|
||||
|
||||
String getGroup(OfflinePlayer base);
|
||||
|
||||
List<String> getGroups(OfflinePlayer base);
|
||||
|
||||
List<String> getGroups();
|
||||
|
||||
boolean canBuild(Player base, String group);
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ import com.earth2me.essentials.perm.impl.ModernVaultHandler;
|
||||
import com.earth2me.essentials.perm.impl.SuperpermsHandler;
|
||||
import com.earth2me.essentials.utils.TriState;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -34,7 +36,7 @@ public class PermissionsHandler implements IPermissionsHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup(final Player base) {
|
||||
public String getGroup(final OfflinePlayer base) {
|
||||
final long start = System.nanoTime();
|
||||
String group = handler.getGroup(base);
|
||||
if (group == null) {
|
||||
@@ -45,16 +47,42 @@ public class PermissionsHandler implements IPermissionsHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups(final Player base) {
|
||||
public List<String> getGroups(final OfflinePlayer base) {
|
||||
final long start = System.nanoTime();
|
||||
List<String> groups = handler.getGroups(base);
|
||||
final List<String> groups = new ArrayList<>();
|
||||
groups.add(defaultGroup);
|
||||
groups.addAll(handler.getGroups(base));
|
||||
checkPermLag(start, String.format("Getting groups for %s", base.getName()));
|
||||
return Collections.unmodifiableList(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups() {
|
||||
final long start = System.nanoTime();
|
||||
List<String> groups = handler.getGroups();
|
||||
if (groups == null || groups.isEmpty()) {
|
||||
groups = Collections.singletonList(defaultGroup);
|
||||
}
|
||||
checkPermLag(start, String.format("Getting groups for %s", base.getName()));
|
||||
checkPermLag(start, "Getting all groups");
|
||||
return Collections.unmodifiableList(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToGroup(OfflinePlayer base, String group) {
|
||||
final long start = System.nanoTime();
|
||||
final boolean result = handler.addToGroup(base, group);
|
||||
checkPermLag(start, String.format("Adding group to %s", base.getName()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromGroup(OfflinePlayer base, String group) {
|
||||
final long start = System.nanoTime();
|
||||
final boolean result = handler.removeFromGroup(base, group);
|
||||
checkPermLag(start, String.format("Removing group from %s", base.getName()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBuild(final Player base, final String group) {
|
||||
return handler.canBuild(base, group);
|
||||
|
||||
+26
-4
@@ -3,6 +3,7 @@ package com.earth2me.essentials.perm.impl;
|
||||
import net.milkbowl.vault.chat.Chat;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
@@ -32,13 +33,34 @@ public abstract class AbstractVaultHandler extends SuperpermsHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup(final Player base) {
|
||||
return perms.getPrimaryGroup(base);
|
||||
public String getGroup(final OfflinePlayer base) {
|
||||
if (base.isOnline()) {
|
||||
return perms.getPrimaryGroup(base.getPlayer());
|
||||
}
|
||||
return perms.getPrimaryGroup(null, base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups(final Player base) {
|
||||
return Arrays.asList(perms.getPlayerGroups(base));
|
||||
public List<String> getGroups(final OfflinePlayer base) {
|
||||
if (base.isOnline()) {
|
||||
return Arrays.asList(perms.getPlayerGroups(base.getPlayer()));
|
||||
}
|
||||
return Arrays.asList(perms.getPlayerGroups(null, base));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups() {
|
||||
return Arrays.asList(perms.getGroups());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToGroup(OfflinePlayer base, String group) {
|
||||
return perms.playerAddGroup(null, base, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromGroup(OfflinePlayer base, String group) {
|
||||
return perms.playerRemoveGroup(null, base, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,11 +70,19 @@ public class LuckPermsHandler extends ModernVaultHandler {
|
||||
// If the player doesn't exist in the UserMap, just skip
|
||||
// Ess will cause performance problems for permissions checks if it attempts to
|
||||
// perform i/o to load the user data otherwise.
|
||||
if (!ess.getUserMap().userExists(target.getUniqueId())) {
|
||||
if (!ess.getUsers().getAllUserUUIDs().contains(target.getUniqueId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUsers().loadUncachedUser(target.getUniqueId());
|
||||
|
||||
// This will occur for first time players during join,
|
||||
// None of our contexts would apply to that kind of person anyway,
|
||||
// lets just skip :O
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = ess.getUser(target);
|
||||
for (Calculator calculator : this.calculators) {
|
||||
calculator.function.apply(user).forEach(value -> consumer.accept(calculator.id, value));
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.perm.IPermissionsHandler;
|
||||
import com.earth2me.essentials.utils.TriState;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
@@ -21,12 +22,27 @@ public class SuperpermsHandler implements IPermissionsHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup(final Player base) {
|
||||
public boolean addToGroup(OfflinePlayer base, String group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromGroup(OfflinePlayer base, String group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup(final OfflinePlayer base) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups(final Player base) {
|
||||
public List<String> getGroups(final OfflinePlayer base) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getGroups() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.FormatUtil;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.earth2me.essentials.utils.VersionUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
import net.ess3.api.events.SignBreakEvent;
|
||||
@@ -18,7 +19,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.data.type.WallSign;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -48,7 +49,7 @@ public class EssentialsSign {
|
||||
final BlockFace[] directions = new BlockFace[] {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST};
|
||||
for (final BlockFace blockFace : directions) {
|
||||
final Block signBlock = block.getRelative(blockFace);
|
||||
if (MaterialUtil.isWallSign(signBlock.getType())) {
|
||||
if (MaterialUtil.isWallSign(signBlock.getType()) || MaterialUtil.isWallHangingSign(signBlock.getType())) {
|
||||
try {
|
||||
if (getWallSignFacing(signBlock) == blockFace && isValidSign(new BlockSign(signBlock))) {
|
||||
return true;
|
||||
@@ -84,13 +85,14 @@ public class EssentialsSign {
|
||||
}
|
||||
|
||||
private static BlockFace getWallSignFacing(final Block block) {
|
||||
try {
|
||||
final WallSign signData = (WallSign) block.getState().getBlockData();
|
||||
return signData.getFacing();
|
||||
} catch (final NoClassDefFoundError | NoSuchMethodError e) {
|
||||
if (VersionUtil.PRE_FLATTENING) {
|
||||
//noinspection deprecation
|
||||
final org.bukkit.material.Sign signMat = (org.bukkit.material.Sign) block.getState().getData();
|
||||
return signMat.getFacing();
|
||||
}
|
||||
|
||||
final Directional signData = (Directional) block.getState().getBlockData();
|
||||
return signData.getFacing();
|
||||
}
|
||||
|
||||
protected final boolean onSignCreate(final SignChangeEvent event, final IEssentials ess) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.earth2me.essentials.ChargeException;
|
||||
import com.earth2me.essentials.Enchantments;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.provider.MaterialTagProvider;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
@@ -66,7 +67,7 @@ public class SignEnchant extends EssentialsSign {
|
||||
|
||||
@Override
|
||||
protected boolean onSignInteract(final ISign sign, final User player, final String username, final IEssentials ess) throws SignException, ChargeException {
|
||||
final ItemStack playerHand = player.getBase().getItemInHand();
|
||||
final ItemStack playerHand = Inventories.getItemInHand(player.getBase());
|
||||
final MaterialTagProvider tagProvider = ess.getMaterialTagProvider();
|
||||
final String itemName = sign.getLine(1);
|
||||
final ItemStack search = itemName.equals("*") || itemName.equalsIgnoreCase("any") || (tagProvider != null && tagProvider.tagExists(itemName) && tagProvider.isTagged(itemName, playerHand.getType())) ? null : getItemStack(itemName, 1, ess);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.Trade.OverflowType;
|
||||
import com.earth2me.essentials.Trade.TradeType;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.craftbukkit.Inventories;
|
||||
import com.earth2me.essentials.utils.MaterialUtil;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import net.ess3.api.IEssentials;
|
||||
@@ -84,10 +85,14 @@ public class SignTrade extends EssentialsSign {
|
||||
|
||||
private Trade rechargeSign(final ISign sign, final IEssentials ess, final User player) throws SignException, ChargeException {
|
||||
final Trade trade = getTrade(sign, 2, AmountType.COST, false, true, ess);
|
||||
if (trade.getItemStack() != null && player.getBase().getItemInHand() != null && trade.getItemStack().getType() == player.getBase().getItemInHand().getType() && MaterialUtil.getDamage(trade.getItemStack()) == MaterialUtil.getDamage(player.getBase().getItemInHand()) && trade.getItemStack().getEnchantments().equals(player.getBase().getItemInHand().getEnchantments())) {
|
||||
ItemStack stack = Inventories.getItemInHand(player.getBase());
|
||||
if (trade.getItemStack() != null && stack != null && !MaterialUtil.isAir(stack.getType()) && trade.getItemStack().getType() == stack.getType() && MaterialUtil.getDamage(trade.getItemStack()) == MaterialUtil.getDamage(stack) && trade.getItemStack().getEnchantments().equals(stack.getEnchantments())) {
|
||||
if (MaterialUtil.isPotion(trade.getItemStack().getType()) && !trade.getItemStack().isSimilar(stack)) {
|
||||
return null;
|
||||
}
|
||||
final int amount = trade.getItemStack().getAmount();
|
||||
if (player.getBase().getInventory().containsAtLeast(trade.getItemStack(), amount)) {
|
||||
final ItemStack stack = player.getBase().getItemInHand().clone();
|
||||
if (Inventories.containsAtLeast(player.getBase(), trade.getItemStack(), amount)) {
|
||||
stack = stack.clone();
|
||||
stack.setAmount(amount);
|
||||
final Trade store = new Trade(stack, ess);
|
||||
addAmount(sign, 2, store, ess);
|
||||
@@ -174,7 +179,7 @@ public class SignTrade extends EssentialsSign {
|
||||
if (amount.compareTo(MINTRANSACTION) < 0 || money.compareTo(MINTRANSACTION) < 0) {
|
||||
throw new SignException(tl("moreThanZero"));
|
||||
}
|
||||
final String newLine = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.shortCurrency(amount, ess).substring(1);
|
||||
final String newLine = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.formatAsCurrency(amount);
|
||||
validateSignLength(newLine);
|
||||
sign.setLine(index, newLine);
|
||||
return;
|
||||
@@ -328,7 +333,7 @@ public class SignTrade extends EssentialsSign {
|
||||
final BigDecimal money = getMoney(split[0], ess);
|
||||
final BigDecimal amount = getBigDecimal(split[1], ess);
|
||||
if (money != null && amount != null) {
|
||||
final String newline = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.shortCurrency(value, ess).substring(1);
|
||||
final String newline = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.formatAsCurrency(value);
|
||||
validateSignLength(newline);
|
||||
sign.setLine(index, newline);
|
||||
return;
|
||||
|
||||
@@ -140,6 +140,13 @@ public class KeywordReplacer implements IText {
|
||||
|
||||
for (int i = 0; i < input.getLines().size(); i++) {
|
||||
String line = input.getLines().get(i);
|
||||
|
||||
// Skip processing b64 encoded items, they will not have keywords in them.
|
||||
if (line.startsWith("@")) {
|
||||
replaced.add(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
final Matcher matcher = KEYWORD.matcher(line);
|
||||
|
||||
while (matcher.find()) {
|
||||
@@ -253,7 +260,7 @@ public class KeywordReplacer implements IText {
|
||||
replacer = Integer.toString(ess.getOnlinePlayers().size() - playerHidden);
|
||||
break;
|
||||
case UNIQUE:
|
||||
replacer = NumberFormat.getInstance().format(ess.getUserMap().getUniqueUsers());
|
||||
replacer = NumberFormat.getInstance().format(ess.getUsers().getUserCount());
|
||||
break;
|
||||
case WORLDS:
|
||||
final StringBuilder worldsBuilder = new StringBuilder();
|
||||
@@ -375,7 +382,10 @@ public class KeywordReplacer implements IText {
|
||||
}
|
||||
|
||||
if (this.replaceSpacesWithUnderscores) {
|
||||
replacer = replacer.replaceAll("\\s", "_");
|
||||
// Don't replace spaces with underscores in command nor escape underscores.
|
||||
if (!line.startsWith("/")) {
|
||||
replacer = replacer.replace("_", "\\_").replaceAll("\\s", "_");
|
||||
}
|
||||
}
|
||||
|
||||
//If this is just a regular keyword, lets throw it into the cache
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.earth2me.essentials.userstorage;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IUserMap {
|
||||
/**
|
||||
* Gets all the UUIDs of every User which has joined.
|
||||
* @return the UUIDs of all Users.
|
||||
*/
|
||||
Set<UUID> getAllUserUUIDs();
|
||||
|
||||
/**
|
||||
* Gets the current amount of users loaded into memory.
|
||||
* @return the amount of users loaded into memory.
|
||||
*/
|
||||
long getCachedCount();
|
||||
|
||||
/**
|
||||
* Gets the amount of users stored by Essentials.
|
||||
* @return the amount of users stored by Essentials.
|
||||
*/
|
||||
int getUserCount();
|
||||
|
||||
User getUser(final UUID uuid);
|
||||
|
||||
User getUser(final Player base);
|
||||
|
||||
User getUser(final String name);
|
||||
|
||||
User loadUncachedUser(final Player base);
|
||||
|
||||
/**
|
||||
* Gets a User by the given UUID in the cache, if present, otherwise loads the user without placing them in the cache.
|
||||
* Ideally to be used when running operations on all stored users.
|
||||
*
|
||||
* @param uuid the UUID of the user to get.
|
||||
* @return the User with the given UUID, or null if not found.
|
||||
*/
|
||||
User loadUncachedUser(final UUID uuid);
|
||||
|
||||
/**
|
||||
* Gets the name to UUID cache.
|
||||
* @return the name to UUID cache.
|
||||
*/
|
||||
Map<String, UUID> getNameCache();
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package com.earth2me.essentials.userstorage;
|
||||
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import com.google.common.io.Files;
|
||||
import net.ess3.api.IEssentials;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ModernUUIDCache {
|
||||
private final IEssentials ess;
|
||||
|
||||
/**
|
||||
* We use a name to uuid map for offline caching due to the following scenario:
|
||||
* * JRoy and mdcfeYT420 play on a server
|
||||
* * mdcfeYT420 changes his name to mdcfe
|
||||
* * mdcfe doesn't log in the server for 31 days
|
||||
* * JRoy changes his name to mdcfeYT420
|
||||
* * mdcfeYT420 (previously JRoy) logs in the server
|
||||
* In a UUID->Name based map, different uuids now point to the same name
|
||||
* preventing any command which allows for offline players from resolving a
|
||||
* given uuid from a given name.
|
||||
* <p>
|
||||
* This map is backed by a file-based cache. If this cache is missing, a new
|
||||
* one is populated by iterating over all files in the userdata folder and
|
||||
* caching the {@code last-account-name} value.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, UUID> nameToUuidMap = new ConcurrentHashMap<>();
|
||||
private final Set<UUID> uuidCache = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private final ScheduledExecutorService writeExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||
private final AtomicBoolean pendingNameWrite = new AtomicBoolean(false);
|
||||
private final AtomicBoolean pendingUuidWrite = new AtomicBoolean(false);
|
||||
private final File nameToUuidFile;
|
||||
private final File uuidCacheFile;
|
||||
|
||||
public ModernUUIDCache(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
this.nameToUuidFile = new File(ess.getDataFolder(), "usermap.bin");
|
||||
this.uuidCacheFile = new File(ess.getDataFolder(), "uuids.bin");
|
||||
loadCache();
|
||||
writeExecutor.scheduleWithFixedDelay(() -> {
|
||||
if (pendingNameWrite.compareAndSet(true, false)) {
|
||||
saveNameToUuidCache();
|
||||
}
|
||||
|
||||
if (pendingUuidWrite.compareAndSet(true, false)) {
|
||||
saveUuidCache();
|
||||
}
|
||||
}, 5, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
protected UUID getCachedUUID(final String name) {
|
||||
return nameToUuidMap.get(getSanitizedName(name));
|
||||
}
|
||||
|
||||
protected Set<UUID> getCachedUUIDs() {
|
||||
return Collections.unmodifiableSet(uuidCache);
|
||||
}
|
||||
|
||||
protected Map<String, UUID> getNameCache() {
|
||||
return Collections.unmodifiableMap(nameToUuidMap);
|
||||
}
|
||||
|
||||
protected int getCacheSize() {
|
||||
return uuidCache.size();
|
||||
}
|
||||
|
||||
protected String getSanitizedName(final String name) {
|
||||
return ess.getSettings().isSafeUsermap() ? StringUtil.safeString(name) : name;
|
||||
}
|
||||
|
||||
protected void updateCache(final UUID uuid, final String name) {
|
||||
if (uuidCache.add(uuid)) {
|
||||
pendingUuidWrite.set(true);
|
||||
}
|
||||
if (name != null) {
|
||||
final String sanitizedName = getSanitizedName(name);
|
||||
final UUID replacedUuid = nameToUuidMap.put(sanitizedName, uuid);
|
||||
if (!uuid.equals(replacedUuid)) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.WARNING, "Replaced UUID during cache update for " + sanitizedName + ": " + replacedUuid + " -> " + uuid);
|
||||
}
|
||||
pendingNameWrite.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeCache(final UUID uuid) {
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uuidCache.remove(uuid)) {
|
||||
pendingUuidWrite.set(true);
|
||||
}
|
||||
|
||||
final Set<String> toRemove = new HashSet<>();
|
||||
for (final Map.Entry<String, UUID> entry : nameToUuidMap.entrySet()) {
|
||||
if (uuid.equals(entry.getValue())) {
|
||||
toRemove.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
for (final String name : toRemove) {
|
||||
nameToUuidMap.remove(name);
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
pendingNameWrite.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCache() {
|
||||
final boolean debug = ess.getSettings().isDebug();
|
||||
|
||||
try {
|
||||
if (!nameToUuidFile.exists()) {
|
||||
if (!nameToUuidFile.createNewFile()) {
|
||||
throw new RuntimeException("Error while creating usermap.bin");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
ess.getLogger().log(Level.INFO, "Loading Name->UUID cache from disk...");
|
||||
}
|
||||
|
||||
nameToUuidMap.clear();
|
||||
|
||||
try (final DataInputStream dis = new DataInputStream(new FileInputStream(nameToUuidFile))) {
|
||||
while (dis.available() > 0) {
|
||||
final String username = dis.readUTF();
|
||||
final UUID uuid = new UUID(dis.readLong(), dis.readLong());
|
||||
final UUID previous = nameToUuidMap.put(username, uuid);
|
||||
if (previous != null && debug) {
|
||||
ess.getLogger().log(Level.WARNING, "Replaced UUID during cache load for " + username + ": " + previous + " -> " + uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while loading Name->UUID cache", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!uuidCacheFile.exists()) {
|
||||
if (!uuidCacheFile.createNewFile()) {
|
||||
throw new RuntimeException("Error while creating uuids.bin");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
ess.getLogger().log(Level.INFO, "Loading UUID cache from disk...");
|
||||
}
|
||||
|
||||
uuidCache.clear();
|
||||
|
||||
try (final DataInputStream dis = new DataInputStream(new FileInputStream(uuidCacheFile))) {
|
||||
while (dis.available() > 0) {
|
||||
final UUID uuid = new UUID(dis.readLong(), dis.readLong());
|
||||
if (uuidCache.contains(uuid) && debug) {
|
||||
ess.getLogger().log(Level.WARNING, "UUID " + uuid + " duplicated in cache");
|
||||
}
|
||||
uuidCache.add(uuid);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while loading UUID cache", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveUuidCache() {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Saving UUID cache to disk...");
|
||||
}
|
||||
|
||||
try {
|
||||
final File tmpMap = File.createTempFile("uuids", ".tmp.bin", ess.getDataFolder());
|
||||
|
||||
writeUuidCache(tmpMap, uuidCache);
|
||||
//noinspection UnstableApiUsage
|
||||
Files.move(tmpMap, uuidCacheFile);
|
||||
} catch (IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while saving UUID cache", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveNameToUuidCache() {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "Saving Name->UUID cache to disk...");
|
||||
}
|
||||
|
||||
try {
|
||||
final File tmpMap = File.createTempFile("usermap", ".tmp.bin", ess.getDataFolder());
|
||||
|
||||
writeNameUuidMap(tmpMap, nameToUuidMap);
|
||||
//noinspection UnstableApiUsage
|
||||
Files.move(tmpMap, nameToUuidFile);
|
||||
} catch (IOException e) {
|
||||
ess.getLogger().log(Level.SEVERE, "Error while saving Name->UUID cache", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void blockingSave() {
|
||||
saveUuidCache();
|
||||
saveNameToUuidCache();
|
||||
}
|
||||
|
||||
public static void writeUuidCache(final File file, Set<UUID> uuids) throws IOException {
|
||||
try (final DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
|
||||
for (final UUID uuid: uuids) {
|
||||
dos.writeLong(uuid.getMostSignificantBits());
|
||||
dos.writeLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeNameUuidMap(final File file, final Map<String, UUID> nameToUuidMap) throws IOException {
|
||||
try (final DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
|
||||
for (final Map.Entry<String, UUID> entry : nameToUuidMap.entrySet()) {
|
||||
dos.writeUTF(entry.getKey());
|
||||
final UUID uuid = entry.getValue();
|
||||
dos.writeLong(uuid.getMostSignificantBits());
|
||||
dos.writeLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
writeExecutor.shutdownNow();
|
||||
blockingSave();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package com.earth2me.essentials.userstorage;
|
||||
|
||||
import com.earth2me.essentials.OfflinePlayerStub;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.NumberUtil;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ModernUserMap extends CacheLoader<UUID, User> implements IUserMap {
|
||||
private final transient IEssentials ess;
|
||||
private final transient ModernUUIDCache uuidCache;
|
||||
private final transient LoadingCache<UUID, User> userCache;
|
||||
|
||||
private final boolean debugPrintStackWithWarn;
|
||||
private final long debugMaxWarnsPerType;
|
||||
private final boolean debugLogCache;
|
||||
private final ConcurrentMap<String, AtomicLong> debugNonPlayerWarnCounts;
|
||||
|
||||
public ModernUserMap(final IEssentials ess) {
|
||||
this.ess = ess;
|
||||
this.uuidCache = new ModernUUIDCache(ess);
|
||||
this.userCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(ess.getSettings().getMaxUserCacheCount())
|
||||
.expireAfterAccess(ess.getSettings().getMaxUserCacheValueExpiry(), TimeUnit.SECONDS)
|
||||
.softValues()
|
||||
.build(this);
|
||||
|
||||
// -Dnet.essentialsx.usermap.print-stack=true
|
||||
final String printStackProperty = System.getProperty("net.essentialsx.usermap.print-stack", "false");
|
||||
// -Dnet.essentialsx.usermap.max-warns=20
|
||||
final String maxWarnProperty = System.getProperty("net.essentialsx.usermap.max-warns", "100");
|
||||
// -Dnet.essentialsx.usermap.log-cache=true
|
||||
final String logCacheProperty = System.getProperty("net.essentialsx.usermap.log-cache", "false");
|
||||
|
||||
this.debugMaxWarnsPerType = NumberUtil.isLong(maxWarnProperty) ? Long.parseLong(maxWarnProperty) : -1;
|
||||
this.debugPrintStackWithWarn = Boolean.parseBoolean(printStackProperty);
|
||||
this.debugLogCache = Boolean.parseBoolean(logCacheProperty);
|
||||
this.debugNonPlayerWarnCounts = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getAllUserUUIDs() {
|
||||
return uuidCache.getCachedUUIDs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCachedCount() {
|
||||
return userCache.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUserCount() {
|
||||
return uuidCache.getCacheSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(final UUID uuid) {
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return userCache.get(uuid);
|
||||
} catch (ExecutionException e) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.WARNING, "Exception while getting user for " + uuid, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(final Player base) {
|
||||
final User user = loadUncachedUser(base);
|
||||
userCache.put(user.getUUID(), user);
|
||||
debugLogCache(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(final String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final User user = getUser(uuidCache.getCachedUUID(name));
|
||||
if (user != null && user.getBase() instanceof OfflinePlayerStub) {
|
||||
if (user.getLastAccountName() != null) {
|
||||
((OfflinePlayerStub) user.getBase()).setName(user.getLastAccountName());
|
||||
} else {
|
||||
((OfflinePlayerStub) user.getBase()).setName(name);
|
||||
}
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
public void addCachedNpcName(final UUID uuid, final String name) {
|
||||
if (uuid == null || name == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
uuidCache.updateCache(uuid, name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Override
|
||||
public User load(final UUID uuid) throws Exception {
|
||||
final User user = loadUncachedUser(uuid);
|
||||
if (user != null) {
|
||||
debugLogCache(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
throw new Exception("User not found!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public User loadUncachedUser(final Player base) {
|
||||
if (base == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
User user = getUser(base.getUniqueId());
|
||||
if (user == null) {
|
||||
debugLogUncachedNonPlayer(base);
|
||||
user = new User(base, ess);
|
||||
} else if (!base.equals(user.getBase())) {
|
||||
ess.getLogger().log(Level.INFO, "Essentials updated the underlying Player object for " + user.getUUID());
|
||||
user.update(base);
|
||||
}
|
||||
uuidCache.updateCache(user.getUUID(), user.getName());
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User loadUncachedUser(final UUID uuid) {
|
||||
User user = userCache.getIfPresent(uuid);
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
|
||||
Player player = ess.getServer().getPlayer(uuid);
|
||||
if (player != null) {
|
||||
// This is a real player, cache their UUID.
|
||||
user = new User(player, ess);
|
||||
uuidCache.updateCache(uuid, player.getName());
|
||||
return user;
|
||||
}
|
||||
|
||||
final File userFile = getUserFile(uuid);
|
||||
if (userFile.exists()) {
|
||||
player = new OfflinePlayerStub(uuid, ess.getServer());
|
||||
user = new User(player, ess);
|
||||
final String accName = user.getLastAccountName();
|
||||
((OfflinePlayerStub) player).setName(accName);
|
||||
// Check to see if there is already a UUID mapping for the name in the name cache before updating it.
|
||||
// Since this code is ran for offline players, there's a chance we could be overriding the mapping
|
||||
// for a player who changed their name to an older player's name, let that be handled during join.
|
||||
//
|
||||
// Here is a senerio which could take place if didn't do the containsKey check;
|
||||
// "JRoyLULW" joins the server - "JRoyLULW" is mapped to 86f39a70-eda7-44a2-88f8-0ade4e1ec8c0
|
||||
// "JRoyLULW" changes their name to "mbax" - Nothing happens, they are yet to join the server
|
||||
// "mdcfe" changes their name to "JRoyLULW" - Nothing happens, they are yet to join the server
|
||||
// "JRoyLULW" (formally "mdcfe") joins the server - "JRoyLULW" is mapped to 62a6a4bb-a2b8-4796-bfe6-63067250990a
|
||||
// The /baltop command is ran, iterating over all players.
|
||||
//
|
||||
// During the baltop iteration, two uuids have the `last-account-name` of "JRoyLULW" creating the
|
||||
// potential that "JRoyLULW" is mapped back to 86f39a70-eda7-44a2-88f8-0ade4e1ec8c0 when the true
|
||||
// bearer of that name is now 62a6a4bb-a2b8-4796-bfe6-63067250990a.
|
||||
uuidCache.updateCache(uuid, (accName == null || uuidCache.getNameCache().containsKey(accName)) ? null : accName);
|
||||
return user;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, UUID> getNameCache() {
|
||||
return uuidCache.getNameCache();
|
||||
}
|
||||
|
||||
public String getSanitizedName(final String name) {
|
||||
return uuidCache.getSanitizedName(name);
|
||||
}
|
||||
|
||||
public void blockingSave() {
|
||||
uuidCache.blockingSave();
|
||||
}
|
||||
|
||||
public void invalidate(final UUID uuid) {
|
||||
userCache.invalidate(uuid);
|
||||
uuidCache.removeCache(uuid);
|
||||
}
|
||||
|
||||
private File getUserFile(final UUID uuid) {
|
||||
return new File(new File(ess.getDataFolder(), "userdata"), uuid.toString() + ".yml");
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
uuidCache.shutdown();
|
||||
}
|
||||
|
||||
private void debugLogCache(final User user) {
|
||||
if (!debugLogCache) {
|
||||
return;
|
||||
}
|
||||
final Throwable throwable = new Throwable();
|
||||
ess.getLogger().log(Level.INFO, String.format("Caching user %s (%s)", user.getName(), user.getUUID()), throwable);
|
||||
}
|
||||
|
||||
private void debugLogUncachedNonPlayer(final Player base) {
|
||||
final String typeName = base.getClass().getName();
|
||||
final long count = debugNonPlayerWarnCounts.computeIfAbsent(typeName, name -> new AtomicLong(0)).getAndIncrement();
|
||||
if (debugMaxWarnsPerType < 0 || count <= debugMaxWarnsPerType) {
|
||||
final Throwable throwable = debugPrintStackWithWarn ? new Throwable() : null;
|
||||
ess.getLogger().log(Level.INFO, "Created a User for " + base.getName() + " (" + base.getUniqueId() + ") for non Bukkit type: " + typeName, throwable);
|
||||
if (count == debugMaxWarnsPerType) {
|
||||
ess.getLogger().log(Level.WARNING, "Essentials will not log any more warnings for " + typeName + ". Please report this to the EssentialsX team.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public final class FormatUtil {
|
||||
private static final Pattern LOGCOLOR_PATTERN = Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]");
|
||||
private static final Pattern URL_PATTERN = Pattern.compile("((?:(?:https?)://)?[\\w-_\\.]{2,})\\.([a-zA-Z]{2,3}(?:/\\S+)?)");
|
||||
//Used to strip ANSI control codes from console
|
||||
private static final Pattern ANSI_CONTROL_PATTERN = Pattern.compile("\u001B(?:\\[0?m|\\[38;2(?:;\\d{1,3}){3}m|\\[([0-9]{1,2}[;m]?){3})");
|
||||
private static final Pattern ANSI_CONTROL_PATTERN = Pattern.compile("[\\x1B\\x9B][\\[\\]()#;?]*(?:(?:(?:;[-a-zA-Z\\d/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d/#&.:=?%@~_]*)*)?\\x07|(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~])");
|
||||
private static final Pattern PAPER_CONTROL_PATTERN = Pattern.compile("(?i)" + (char) 0x7f + "[0-9A-FK-ORX]");
|
||||
|
||||
private FormatUtil() {
|
||||
|
||||
@@ -27,6 +27,8 @@ public final class MaterialUtil {
|
||||
private static final Set<Material> POTIONS;
|
||||
private static final Set<Material> SIGN_POSTS;
|
||||
private static final Set<Material> WALL_SIGNS;
|
||||
private static final Set<Material> HANGING_SIGNS;
|
||||
private static final Set<Material> HANGING_WALL_SIGNS;
|
||||
|
||||
private static final Set<Material> HELMETS;
|
||||
private static final Set<Material> CHESTPLATES;
|
||||
@@ -71,7 +73,7 @@ public final class MaterialUtil {
|
||||
MOB_HEADS = EnumUtil.getAllMatching(Material.class, "SKELETON_SKULL",
|
||||
"SKELETON_WALL_SKULL", "WITHER_SKELETON_SKULL", "WITHER_SKELETON_WALL_SKULL",
|
||||
"CREEPER_HEAD", "CREEPER_WALL_HEAD", "ZOMBIE_HEAD", "ZOMBIE_WALL_HEAD", "DRAGON_HEAD"
|
||||
, "DRAGON_WALL_HEAD");
|
||||
, "DRAGON_WALL_HEAD", "PIGLIN_HEAD", "PIGLIN_WALL_HEAD");
|
||||
|
||||
PLAYER_HEADS = EnumUtil.getAllMatching(Material.class, "PLAYER_HEAD", "PLAYER_WALL_HEAD");
|
||||
|
||||
@@ -83,14 +85,30 @@ public final class MaterialUtil {
|
||||
"DARK_OAK_SIGN", "JUNGLE_SIGN",
|
||||
"OAK_SIGN", "SPRUCE_SIGN",
|
||||
"CRIMSON_SIGN", "WARPED_SIGN",
|
||||
"MANGROVE_SIGN");
|
||||
"MANGROVE_SIGN", "CHERRY_SIGN",
|
||||
"BAMBOO_SIGN");
|
||||
|
||||
WALL_SIGNS = EnumUtil.getAllMatching(Material.class, "WALL_SIGN",
|
||||
"ACACIA_WALL_SIGN", "BIRCH_WALL_SIGN",
|
||||
"DARK_OAK_WALL_SIGN", "JUNGLE_WALL_SIGN",
|
||||
"OAK_WALL_SIGN", "SPRUCE_WALL_SIGN",
|
||||
"CRIMSON_WALL_SIGN", "WARPED_WALL_SIGN",
|
||||
"MANGROVE_WALL_SIGN");
|
||||
"MANGROVE_WALL_SIGN", "CHERRY_WALL_SIGN",
|
||||
"BAMBOO_WALL_SIGN");
|
||||
|
||||
HANGING_SIGNS = EnumUtil.getAllMatching(Material.class, "ACACIA_HANGING_SIGN", "BIRCH_HANGING_SIGN",
|
||||
"DARK_OAK_HANGING_SIGN", "JUNGLE_HANGING_SIGN",
|
||||
"OAK_HANGING_SIGN", "SPRUCE_HANGING_SIGN",
|
||||
"CRIMSON_HANGING_SIGN", "WARPED_HANGING_SIGN",
|
||||
"MANGROVE_HANGING_SIGN", "CHERRY_HANGING_SIGN",
|
||||
"BAMBOO_HANGING_SIGN");
|
||||
|
||||
HANGING_WALL_SIGNS = EnumUtil.getAllMatching(Material.class, "ACACIA_WALL_HANGING_SIGN", "BIRCH_WALL_HANGING_SIGN",
|
||||
"DARK_OAK_WALL_HANGING_SIGN", "JUNGLE_WALL_HANGING_SIGN",
|
||||
"OAK_WALL_HANGING_SIGN", "SPRUCE_WALL_HANGING_SIGN",
|
||||
"CRIMSON_WALL_HANGING_SIGN", "WARPED_WALL_HANGING_SIGN",
|
||||
"MANGROVE_WALL_HANGING_SIGN", "CHERRY_WALL_HANGING_SIGN",
|
||||
"BAMBOO_WALL_HANGING_SIGN");
|
||||
}
|
||||
|
||||
private MaterialUtil() {
|
||||
@@ -152,12 +170,20 @@ public final class MaterialUtil {
|
||||
return WALL_SIGNS.contains(material);
|
||||
}
|
||||
|
||||
public static boolean isHangingSign(final Material material) {
|
||||
return HANGING_SIGNS.contains(material);
|
||||
}
|
||||
|
||||
public static boolean isWallHangingSign(final Material material) {
|
||||
return HANGING_WALL_SIGNS.contains(material);
|
||||
}
|
||||
|
||||
public static boolean isEditableBook(final Material material) {
|
||||
return EDITABLE_BOOKS.contains(material);
|
||||
}
|
||||
|
||||
public static boolean isSign(final Material material) {
|
||||
return isSignPost(material) || isWallSign(material);
|
||||
return isSignPost(material) || isWallSign(material) || isHangingSign(material) || isWallHangingSign(material);
|
||||
}
|
||||
|
||||
public static boolean isSkull(final Material material) {
|
||||
|
||||
@@ -25,6 +25,9 @@ public final class StringUtil {
|
||||
|
||||
//Used to clean strings/names before saving as filenames/permissions
|
||||
public static String safeString(final String string) {
|
||||
if (string == null) {
|
||||
return null;
|
||||
}
|
||||
return STRICTINVALIDCHARS.matcher(string.toLowerCase(Locale.ENGLISH)).replaceAll("_");
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,10 @@ public final class VersionUtil {
|
||||
public static final BukkitVersion v1_17_1_R01 = BukkitVersion.fromString("1.17.1-R0.1-SNAPSHOT");
|
||||
public static final BukkitVersion v1_18_2_R01 = BukkitVersion.fromString("1.18.2-R0.1-SNAPSHOT");
|
||||
public static final BukkitVersion v1_19_R01 = BukkitVersion.fromString("1.19-R0.1-SNAPSHOT");
|
||||
public static final BukkitVersion v1_19_2_R01 = BukkitVersion.fromString("1.19.2-R0.1-SNAPSHOT");
|
||||
public static final BukkitVersion v1_19_4_R01 = BukkitVersion.fromString("1.19.4-R0.1-SNAPSHOT");
|
||||
public static final BukkitVersion v1_20_1_R01 = BukkitVersion.fromString("1.20.1-R0.1-SNAPSHOT");
|
||||
|
||||
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_2_R01);
|
||||
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_4_R01, v1_20_1_R01);
|
||||
|
||||
public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01);
|
||||
|
||||
@@ -70,10 +71,12 @@ public final class VersionUtil {
|
||||
builder.put("io.akarin.server.Config", SupportStatus.DANGEROUS_FORK);
|
||||
|
||||
// Forge - Doesn't support Bukkit
|
||||
builder.put("net.minecraftforge.common.MinecraftForge", SupportStatus.UNSTABLE);
|
||||
// The below translates to net.minecraftforge.common.MinecraftForge
|
||||
builder.put(dumb(new int[] {110, 101, 116, 46, 109, 105, 110, 101, 99, 114, 97, 102, 116, 102, 111, 114, 103, 101, 46, 99, 111, 109, 109, 111, 110, 46, 77, 105, 110, 101, 99, 114, 97, 102, 116, 70, 111, 114, 103, 101}, 40), SupportStatus.UNSTABLE);
|
||||
|
||||
// Fabric - Doesn't support Bukkit
|
||||
builder.put("net.fabricmc.loader.launch.knot.KnotServer", SupportStatus.UNSTABLE);
|
||||
// The below translates to net.fabricmc.loader.launch.knot.KnotServer
|
||||
builder.put(dumb(new int[] {110, 101, 116, 46, 102, 97, 98, 114, 105, 99, 109, 99, 46, 108, 111, 97, 100, 101, 114, 46, 108, 97, 117, 110, 99, 104, 46, 107, 110, 111, 116, 46, 75, 110, 111, 116, 83, 101, 114, 118, 101, 114}, 42), SupportStatus.UNSTABLE);
|
||||
|
||||
// Misc translation layers that do not add NMS will be caught by this
|
||||
if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_17_R1)) {
|
||||
@@ -344,4 +347,21 @@ public final class VersionUtil {
|
||||
return supported;
|
||||
}
|
||||
}
|
||||
|
||||
private static String dumb(final int[] clazz, final int len) {
|
||||
final char[] chars = new char[clazz.length];
|
||||
|
||||
for (int i = 0; i < clazz.length; i++) {
|
||||
chars[i] = (char) clazz[i];
|
||||
}
|
||||
|
||||
final String decode = String.valueOf(chars);
|
||||
|
||||
if (decode.length() != len) {
|
||||
System.exit(1);
|
||||
return "why do hybrids try to bypass this?";
|
||||
}
|
||||
|
||||
return decode;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 224 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user