Compare commits

...

No commits in common. "main" and "plugins" have entirely different histories.

59 changed files with 36770 additions and 425 deletions

View File

@ -1,23 +0,0 @@
# Administration Commands for Admins and Mods + Support Roles
## Admin Command List:
/padmin # player administration
Binding keys and saving the keybinds:bind p chat.say 0 /padminor:bind p "chat.say 0 /padmin"Then to save it:writecfg
playeradministration.closeui
keybind: bind o "chat.say /padmin"
keybind: bind p "playeradministration.closeui"
bind [leftshift+P] "chat.say /padmin" # i gots a better idea!
bind p playeradministration.closeui
bind o clear # How to unbind
/perms # player / group permission
/other mods admins have that others don't, so we can have a full list everyone can view to know who to get in contact with.
## Mod commands list:
### Support
/mute # idk just need to know what staff commands they have.

View File

@ -1,34 +0,0 @@
Here are the commands:
Go to PuTTy
login, go to the right folder, i used lgsm to install rust so this is how it updates also.
https://linuxgsm.com/lgsm/rustserver/
./rustserver // List Full commands
./rustserver backup // backup the server before you do anything as the update could fuck everything up. I backup the files through filezilla locally also (plugins and config files only)
./rustserver check-update // check local and remote build
./rustserver stop
./rustserver update // This will update rust, may wipe the server not sure // This killed the server last time so please be weary of running it. Only on main updates
./rustserver validate // validate files, this will overwrite some rust files like mods and stuff, why you must install mods after, but idk how to update and then update oxide, because they have to be on the same update. Can't update till oxide updates.
./rustserver mods-update // I reckon will just update the Oxide, not sure about plugins. shouldn't update plugins no. MAKE SURE RUST UPDATE MATCHES
./rustserver start
./rustserver restart
./rustserver details
./rustserver debug
./rustserver backup
./rustserver monitor // monitors the server and if it goes down, will restart it automatically, can configure with crontab -e to start on boot also. (if server restarts)
./rustserver console // watch rustserver boot but doesnt really watch it, did at first. // it now works, shows server boot. I changed some lines to log it locally so that kind of fucked it up.
ctrl+b the press "d" to exit console. (ctrl+c will fuck it up and you must stop and start server again)
/home/ruster/rustserver/serverfiles/rustserver.txt // Boot Log location, if server isn't booting check here for logs.
To wipe the map:
./rustserver wipe
./rustserver full-wipe // Blueprint wipe

View File

@ -1,44 +0,0 @@
# How to login to filezilla or putty to transfer files
1. Filezilla is to upload plugins and/or edit files.
2. PuTTy is to restart the server if need be.
3. RustAdmin for RCON support and easy commands. rconpassword=redacted
## Filezilla:
IP: 35.208.110.204
User: ruster
pw: Key file sent in discord
## Putty:
IP: rsa-key-20210207@35.208.110.204
Settings >> SSH >> AUTH >> Add the private key file for authentication >> Back to "Session" >> Save (make sure to name it) >> Open
rsakey Pass: Redacted
open in text document save as Rust-SSH-Key-Private.ppk, use putty gen to open, Password is "redacted"
PuTTY-User-Key-File-2: ssh-rsa
Encryption: aes256-cbc
Comment: rsa-key-20210207
Public-Lines: 6
AAAAB3NzaC1yc2EAAAABJQAAAQEAx1RbYUvGL3BaYalt2jYqf3FyAyZfdrO2NEWW
cKGx2qmT2xC3dESIDeaFn9/lKDuGj8mhT944S04Dk0UegtC2vOwZF+Bd2kKzJIr7
42i9LCrup4cMCU7yDkf3omW34ozZ1t9/UZ6ZDdTkp7+OEJh6wqFKj7nenedKhwUU
JIE7krcrbn83+PtwHmlsHHcte1QxipMGYtzStUSOAieJQrt794u9YC2G7Gan3Z7i
rXGxLA8cE2oJ8hqVsdE7RqBdb+EwBe/K2cLxbKDjlMSW0T+zNXTNPbOM7byzya4o
QJiX9mMQF/XrGtYjR+KJeZa45ILCH8OBs121/TPG4ZQcCUf/3w==
Private-Lines: 14
nCye5Gm0gKfbWEoK3WEsEMKGUqvlvFYHlrEiNoJ2ezBrol5ZJ6RE4afmjBabjl7t
WNpxBANI65bqG9HkdakDE96wS4hGLOqFRri1s+8qcC2ppkQ9eVCqumDXCelDwphz
R5DqumzqQa758dKCvGz6xIK/FSNysivKeEWE7AhgLDPqfdcZCW5Xw45+kVPRCq0J
gl0vn8PPQhEzYcPYnXs3j+zy3EHtJbs48MOvwoOyP3ci9MEIToH05majz1wJdymp
YngT9lNwJhh0bqpvKYnoCNV6h7cwCGPLJXlVpJ1XU1vBOTgl+CsTPSVNlEE80xi3
1VqvkESyr6PqzRe1BUSBGHc+P9C55hfWjTV6TBh8+5K0P/FBscVrAmtwPvJo3LjO
zfhBFYl02A5ZoYl4jxAxjbpZoxhIUcNsBk0hLsekE6uKN5OkS3dowx2cFnDFNb8c
Pt06tf3kNtoY/u/X535YPF75DncReYj9fxPDD4UN7KveajYSo/vNSE1yFLjKLHZW
+2TgHT4nlq6JCqRB85qr5mSj2KdPX3ZePl2vkE82p4zIRxwXWfyDIS63NoZGIAuk
WsNAJ7wz3bxn1VV4Fyuud9s6F0yq//bACVgAlAECssau8Hi1kPT7jmVuuc3GVtZ7
Twc1qDCV3TeMPp9sBv8sPMwjDPXk3pbHFBj438xBz3Y9R6n32FJhFsp2VJ5qpPqt
CQXAuF6sBUnSHQg8XkUIMWjJHcsTp2cwvALUNvVQ/oEmTvIL6z4XhQzVnmOaeYQI
Ode7k6Yv9EpXrrGeFfPSUUf5P95qhaU1h9hNueocZzkzgJ4ITdyIM+MfKkG2IxU7
DgjLpmY+lHCRJmSYXzCjtLln3MUWRTvYe6PVFHZcrJgaYKDGf4a+jVn5dhGkbqyd
Private-MAC: 9a969c14b6a42caa0fdf5b2de4ee5d2afbc3b288

View File

@ -1,49 +0,0 @@
# Permissions and groups:
These commands can be ran in RustAdmin. "Type a command to execute", takes forever implemnting permissions this way. we need a gui or something.
but we can just slowly give permissions for the time bing.
1st command: (To show groups so you can add members if needed, which should be needed once we get donation plugin setup. Only to make new mods/admins)
oxide.show groups
oxide.grant group admin skinbox.use
oxide.grant group vip skinbox.use
oxide.grant group admin skinbox.admin
oxide.grant group admin permissionsmanager.allowed
oxide.show perms 'group_name' // to see perms of a group
oxide.show group admin // to see users of a group
oxide.usergroup add <player_name or STEAM64_ID> group_name
oxide.usergroup remove <player_name or STEAM64_ID> group_name
oxide.revoke group admin coolplugin.use
oxide.group add supporters
oxide.group remove <group>
oxide.group set supporters “[Server Supporters]” // Group title set
oxide.group set supporters “[Server Supporters]” 1 // Change group rank
oxide.group parent tier_2 tier_1 // can also tier the groups for vip gold and vip diamond so auto add perms from lower group
oxide.grant user <user_name or STEAM64_ID> <permission>
oxide.revoke user <user_name or STEAM64_ID> <permission>
oxide.show user user_name // show players assigned perms
oxide.show perm coolplugin.use // show who is assigned to that perm
oxide.group parent <parentgroup><childgroup>
oxide.group set <group><"[Title]"><rank>
Setting the parent group of another group. A group will inherit all permissions from its parent group.
oxide.group parent admin default
**** Don't forget to log out and back in to set permissions!
RUST GROUPS -- NOT PART OF OXIDE
ownerid 76561198106966240 // LVL 2 auth on everything
moderatorid <your steam 64 id> // lvl 1 auth on everything
idk what moderator entails yet, but soon will find out. No reason to give out that permission, just use oxide groups.
/perms # Use for permission manager in game, fixed using with imagelibrary from umod

View File

@ -1,107 +0,0 @@
# Rust Server Plugins + Oxide Perms Starting
## Main Plugins Here:
- https://umod.org/plugins/gather-manager
- https://umod.org/plugins/time-of-day // for short nights
- https://umod.org/plugins/clear-night
- https://umod.org/plugins/discord-auth
- https://umod.org/plugins/quick-smelt
- https://umod.org/plugins/stack-size-controller
- https://umod.org/plugins/better-loot // for barrels and shit and crates
- https://umod.org/plugins/better-chat // to see mods and admins in chat
- https://umod.org/plugins/crafting-controller // quicker crafting
- https://umod.org/plugins/fancy-drop
- https://umod.org/plugins/loading-messages // advertise discord
- https://umod.org/plugins/unburnable-meat
- https://umod.org/plugins/advert-messages
- https://umod.org/plugins/wounded-screams
- https://umod.org/plugins/info-panel
- https://umod.org/plugins/server-info
- https://umod.org/plugins/welcome-screen
- https://umod.org/plugins/image-library
- https://umod.org/plugins/compound-options
- https://umod.org/plugins/quick-sort
- https://umod.org/plugins/clans
### Moderator Plugins:
- https://umod.org/plugins/vanish
- https://umod.org/plugins/better-chat-mute
- https://umod.org/plugins/admin-panel // 9 months old
- https://umod.org/plugins/remover-tool
- https://umod.org/plugins/godmode
- https://umod.org/plugins/admin-logger
- https://umod.org/plugins/player-administration // 30 days old
### Donator Options below:
https://umod.org/plugins/active-sort
https://umod.org/plugins/furnace-splitter
https://umod.org/plugins/skins
https://umod.org/plugins/rust-kits
https://umod.org/plugins/wipe-kits
Skinbox - already added
### Optional Plugins: (ideas to build from)
https://umod.org/plugins/godmode
https://umod.org/plugins/backpacks // maybe for donators
https://umod.org/plugins/skip-night-vote
https://umod.org/plugins/magic-panel
https://umod.org/plugins/loading-messages
https://umod.org/plugins/dangerous-treasures
https://umod.org/plugins/raidable-bases
https://umod.org/plugins/friends
https://umod.org/plugins/chat-notice // Sound effect for receiver messages.
https://umod.org/plugins/discord-server-stats
https://umod.org/plugins/bounty // Put a bounty on the clan in first place.
https://umod.org/plugins/raid-alarm
https://umod.org/plugins/clear-repair
---
## Already added plugins: (Please move to here after)
In game run this:
oxide.version // to see oxide version
moderatorid 76561198106966240 // to add someone to moderator (rust moderator not oxide)
server.writecfg (write rust server config and not oxide use one below to reload oxide plugin configs)
log off and back on to the server to be granted their new roles
**RELOAD OXIDE PLUGIN CONFIGS:
oxide.reload QuickSmelt
oxide.grant group default quicksmelt.use
---
## Permissions and groups:
oxide.show groups
oxide.grant group admin skinbox.use
oxide.grant group vip skinbox.use
oxide.grant group admin skinbox.admin
oxide.grant group admin permissionsmanager.allowed
oxide.show perms group_name // to see perms of a group
oxide.show group admin // to see users of a group
oxide.usergroup add <player_name or STEAM64_ID> group_name
oxide.usergroup remove <player_name or STEAM64_ID> group_name
oxide.revoke group admin coolplugin.use
oxide.group add supporters
oxide.group set supporters “[Server Supporters]” // Group title set
oxide.group set supporters “[Server Supporters]” 1 // Change group rank
oxide.group parent tier_2 tier_1 // can also tier the groups for vip gold and vip diamond so auto add perms from lower group
oxide.grant user <user_name or STEAM64_ID> <permission>
oxide.revoke user <user_name or STEAM64_ID> <permission>
oxide.show user user_name // show players assigned perms
oxide.show perm coolplugin.use // show who is assigned to that perm

View File

@ -1,40 +0,0 @@
# Potential Plugin Ideas and to buy
### Paid:
- https://rustworkshop.space/resources/admin-restrict.137/
- https://rustworkshop.space/resources/kits.29/
- https://rustworkshop.space/resources/clan-outfits.107/
- https://rustworkshop.space/resources/give-modified.141/
- https://rustworkshop.space/resources/stacks-plus.111/
- https://rustworkshop.space/resources/alerts-plus-raid-alerts.183/
**Scrap wheel plugin boiiiiii
- https://rustworkshop.space/resources/wheel-bets.80/
- https://rustworkshop.space/resources/categories/free-plugins.6/
- https://rustworkshop.space/resources/xp-rewards.33/
**Admin Menu paid
- https://www.chaoscode.io/resources/admin-menu.59/
- https://www.chaoscode.io/resources/stacksextended.35/
- https://www.chaoscode.io/resources/alphaloot.13/
- https://www.chaoscode.io/resources/discord-clans.210/
- https://www.chaoscode.io/resources/discordrewards.136/
- https://www.chaoscode.io/resources/dynamiccupshare.20/
**Score
- https://rustworkshop.space/resources/score.220/ // paid plugin 15$
- ^^^^^^^^^^ These two mixed together? That's almost 100$ on plugins fuckkkk.
- SQL RANKS (SCOREBOARD maybe the one that OnlyRust has)
- https://www.chaoscode.io/resources/sqlranks.115/
- https://www.chaoscode.io/resources/sqlstats.114/
- https://www.chaoscode.io/resources/sqlstatistics.116/
- https://www.chaoscode.io/resources/clans-reborn.14/
Unpaid:
- ** broadcast roulette wins
- https://umod.org/plugins/roulette-broadcast
- ** kdr scoreboard, add to another scoreboard later.
- https://umod.org/plugins/kdr-scoreboard
- https://codefling.com/file/518-drone-patrol/

View File

@ -1,26 +0,0 @@
# SickGaming Rust Server
**Website:**
https://www.sickgaming.net/
**Rust Server Forum:**
https://www.sickgaming.net/forum-91.html
- Check "Projects" tab above to see what things need "To Be done", "In Progress", and what's "Done"
- Issues tab for current issues with code that need help or an issue you will come back to.
- Next to "Branches" you should see "Main", click it to pull a drop down list of all our branches. Branch "origin/plugins" is an active directory of our plugins. git push on putty can push all changes in the oxide/plugin folder.
The links below will be able to help you get through some of the tasks quicker.
Links to other pages:
- [Administration-Commands](Administration-Commands.md)
- [How-To-Update-Rust+Oxide](How-To-Update-Rust+Oxide)
- [Login-to-Filezilla-and-PuTTy](Login-to-Filezilla-and-PuTTy.md)
- [Permissions-and-Groups](Permissions-and-Groups.md)
- [Plugins-and-Oxide-Perms-Starting](Plugins-and-Oxide-Perms-Starting.md)
- [Potential-Plugin-Ideas](Potential-Plugin-Ideas.md)
- [Rust-Server-Install-Start-to-Finish](Rust-Server-Install-Start-to-Finish.md)
- [Server-Title-Description-Images](Server-Title-Description-Images.md)
- [SkinBox-Info](SkinBox-Info.md)

View File

@ -1,40 +0,0 @@
# Complete Rust Install Method
Use putty, login to server (SSH shell)
Login to user, shouldn't be root, but doesn't matter if testing.
35.209.133.227
Rustication SickProdigy@gmail.com
if you ctrl z by accident
type "fg" next line to pull back up that process!
sudo apt update
sudo apt upgrade
sudo dpkg --add-architecture i386; sudo apt update; sudo apt install curl wget file tar bzip2 gzip unzip bsdmainutils python util-linux ca-certificates binutils bc jq tmux netcat lib32gcc1 lib32stdc++6 steamcmd lib32z1
sudo adduser ruster
su - ruster
MySecretPassword
mkdir ruster
wget -O linuxgsm.sh https://linuxgsm.sh && chmod +x linuxgsm.sh && bash linuxgsm.sh rustserver // Install LinuxGSM the files that makes using rust easy.
./rustserver install // didn't add every dpkg from earlier command had to exit exit sudo (whatever dependencies where missing)
Reran above command // worked
./rustserver start
connect 35.208.110.204:28015 // had to turn to static, was having issues with firewall. after creating fresh vm and made ip static was able to connect after 15 minutes.
./rustserver console
CTRL+b d // how to exit, DO NOT CTRL-C this will fudge stuff up, type in console type "fg" enter and maybe you can bring it back if it's still up.
./rustserver mods-install
./rustserver stop
./rustserver start
In game run this:
oxide.version // This will show oxide is installed or not or working or not basically.

View File

@ -1,30 +0,0 @@
# Server Title, Description, and images
Had troubles remembering this so want to write it here.
1.
server.description: “Last Wiped: 2/8\n 2x Modded server, with active admins\n 4.2k Map Size\n Monthly BP & Map Wipes\n https://discord.gg/eQj8wyY”
2.
server.description "Welcome to [US] SickGaming.net Main 2x Vanilla PVP Server!\n2750 Map Size for HIGH PVP (use discord to suggest different)\nhttps://discord.gg/eQj8wyY\n-Mostly built to feel vanilla with a speedier pace.\n-Half Smelt/Crafting Speed, Shared BP's and doors.\n-2.5 Sulfur and HQM gather rate. Better Loot, Clans, Furnace Sort.\n-VIP: SkinBox, Kits, small droppable Backpack, and more!\n--Active Admins\n-Weekly Bp/Map Wipes for COMPETITION\n-Scoreboard is being updated"
3.
Welcome to [US] SickGaming.net Main 2x Vanilla PVP Server!
2750 Map Size for HIGH PVP (use discord to suggest different)
https://discord.gg/eQj8wyY\n-Mostly built to feel vanilla with a speedier pace.
-Half Smelt/Crafting Speed, Shared BP's and doors.
-2.5 Sulfur and HQM gather rate. Better Loot, Clans, Furnace Sort.
-VIP: SkinBox, Kits, small droppable Backpack, and more!
--Active Admins
-Weekly Bp/Map Wipes for COMPETITION
-Scoreboard is being updated"
Another Example: (so we can have multiple versions going around that touch different words, SEO friendly)
Welcome to [US] SickGaming.net Main 2x Vanilla PVP Server!
https://i.imgur.com/SUWmYq9.png
/home/ruster/rustserver/serverfiles/server/rustserver/cfg
^^ to change server description **************************

View File

@ -1,32 +0,0 @@
# Skinbox Information and Examples
Help on the SkinBox:
"skinbox.use" - Required to open the SkinBox
"skinbox.admin" - Required to use the admin commands
"skinbox.ignorecost" - Ignores usage cost for players with this permission
"skinbox.ignorecooldown" - Ignores cooldowns for players with this permission
"Custom permissions per skin": {
"skinbox.example1": [
9990,
9991,
9992
],
"skinbox.example2": [
9993,
9994,
9995
],
"skinbox.example3": [
9996,
9997,
9998
]
}
skinbox.addcollection - Adds all the skins in the collection
(Ex: skinbox.addcollection 659627304)
skinbox.removecollection - Removes all the skins in the collection
(Ex: skinbox.addcollection 659627304)

57
config/BetterLoot.json Normal file
View File

@ -0,0 +1,57 @@
{
"Generic": {
"blueprintProbability": 0.11,
"listUpdatesOnLoaded": true,
"removeStackedContainers": true,
"WatchedPrefabs": [
"assets/bundled/prefabs/radtown/crate_basic.prefab",
"assets/bundled/prefabs/radtown/crate_elite.prefab",
"assets/bundled/prefabs/radtown/crate_mine.prefab",
"assets/bundled/prefabs/radtown/crate_normal.prefab",
"assets/bundled/prefabs/radtown/crate_normal_2.prefab",
"assets/bundled/prefabs/radtown/crate_normal_2_food.prefab",
"assets/bundled/prefabs/radtown/crate_normal_2_medical.prefab",
"assets/bundled/prefabs/radtown/crate_tools.prefab",
"assets/bundled/prefabs/radtown/crate_underwater_advanced.prefab",
"assets/bundled/prefabs/radtown/crate_underwater_basic.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm ammo.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm c4.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm construction resources.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm construction tools.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm food.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm medical.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm res.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm tier1 lootbox.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm tier2 lootbox.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm tier3 lootbox.prefab",
"assets/bundled/prefabs/radtown/vehicle_parts.prefab",
"assets/bundled/prefabs/radtown/foodbox.prefab",
"assets/bundled/prefabs/radtown/loot_barrel_1.prefab",
"assets/bundled/prefabs/radtown/loot_barrel_2.prefab",
"assets/bundled/prefabs/autospawn/resource/loot/loot-barrel-1.prefab",
"assets/bundled/prefabs/autospawn/resource/loot/loot-barrel-2.prefab",
"assets/bundled/prefabs/autospawn/resource/loot/trash-pile-1.prefab",
"assets/bundled/prefabs/radtown/loot_trash.prefab",
"assets/bundled/prefabs/radtown/minecart.prefab",
"assets/bundled/prefabs/radtown/oil_barrel.prefab",
"assets/prefabs/npc/m2bradley/bradley_crate.prefab",
"assets/prefabs/npc/patrol helicopter/heli_crate.prefab",
"assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab",
"assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate_oilrig.prefab",
"assets/prefabs/misc/supply drop/supply_drop.prefab"
]
},
"Loot": {
"enableHammerLootCycle": false,
"hammerLootCycleTime": 3,
"lootMultiplier": 1,
"scrapMultiplier": 1
},
"Rarity": {
"Override": {
"autoturret": 4,
"lmg.m249": 4,
"targeting.computer": 3
}
}
}

File diff suppressed because it is too large Load Diff

51
config/GatherManager.json Normal file
View File

@ -0,0 +1,51 @@
{
"Messages": {
"Dispensers": "Resource Dispensers",
"Excavators": "Excavators",
"HelpText": "/gather - Shows you detailed gather information.",
"HelpTextAdmin": "To change the resources gained by gathering use the command:\r\ngather.rate <type:dispenser|pickup|quarry|survey> <resource> <multiplier>\r\nTo change the amount of resources in a dispenser type use the command:\r\ndispenser.scale <dispenser:tree|ore|corpse> <multiplier>\r\nTo change the time between Mining Quarry gathers:\r\nquarry.tickrate <seconds>",
"HelpTextMiningQuarrySpeed": "Time between Mining Quarry gathers: {0} second(s).",
"HelpTextPlayer": "Resources gained from gathering have been scaled to the following:",
"HelpTextPlayerDefault": "Default values.",
"HelpTextPlayerGains": "Resources gained from {0}:",
"InvalidArgumentsDispenserType": "Invalid arguments supplied! Use dispenser.scale <dispenser:tree|ore|corpse> <multiplier>",
"InvalidArgumentsGather": "Invalid arguments supplied! Use gather.rate <type:dispenser|pickup|quarry|survey> <resource> <multiplier>",
"InvalidArgumentsMiningQuarrySpeed": "Invalid arguments supplied! Use quarry.rate <time between gathers in seconds>",
"InvalidDispenser": "{0} is not a valid dispenser. Check gather.dispensers for a list of available options.",
"InvalidMiningQuarrySpeed": "You can't set the speed lower than 1 second!",
"InvalidModifier": "Invalid modifier supplied! The new modifier always needs to be bigger than 0!",
"InvalidResource": "{0} is not a valid resource. Check gather.resources for a list of available options.",
"MiningQuarries": "Mining Quarries",
"ModifyDispenser": "You have set the resource amount for {0} dispensers to x{1}",
"ModifyMiningQuarrySpeed": "The Mining Quarry will now provide resources every {0} seconds.",
"ModifyResource": "You have set the gather rate for {0} to x{1} from {2}.",
"ModifyResourceRemove": "You have reset the gather rate for {0} from {1}.",
"NotAllowed": "You don't have permission to use this command.",
"Pickups": "pickups",
"SurveyCharges": "Survey Charges"
},
"Options": {
"ExcavatorBeltSpeedMax": 0.1,
"ExcavatorResourceModifiers": {},
"ExcavatorResourceTickRate": 3.0,
"ExcavatorTimeForFullResources": 120.0,
"GatherDispenserModifiers": {},
"GatherResourceModifiers": {
"*": 2.0
},
"MiningQuarryResourceTickRate": 5.0,
"PickupResourceModifiers": {
"*": 2.0
},
"QuarryResourceModifiers": {
"*": 2.0
},
"SurveyResourceModifiers": {
"*": 2.0
}
},
"Settings": {
"ChatPrefix": "Gather Manager",
"ChatPrefixColor": "#008000ff"
}
}

44
config/Kits.json Normal file
View File

@ -0,0 +1,44 @@
{
"NPC - GUI Kits": {
"0": {
"description": "Welcome on this server! Here is a list of free kits that you can get.<color=green>Enjoy your stay</color>",
"kits": [
"kit1",
"kit2"
]
},
"1235439": {
"description": "Welcome on this server! Here is a list of free kits that you can get.<color=green>Enjoy your stay</color>",
"kits": [
"kit1",
"kit2"
]
},
"8753201223": {
"description": "<color=red>VIPs Kits</color>",
"kits": [
"kit1",
"kit3"
]
}
},
"CopyPaste - Parameters": [
"deployables",
"true",
"inventories",
"true"
],
"Custom AutoKits": {
"0": "KitName",
"1": "KitName",
"2": "KitName"
},
"Kit - Logging": false,
"Show All Kits": false,
"Background - URL": "",
"Wipe kit data on map wipe": false,
"Kit Names & Cooldowns - Cooldowns (minutes)": {
"kitName1": 20.0,
"kitName2": 30.0
}
}

View File

@ -0,0 +1,11 @@
{
"Chat - Message colour": "<color=white>",
"Chat - Title colour": "<color=orange>",
"GUI - All = per page": false,
"GUI - Inherited colour": "0.9 0.6 0.17 1",
"GUI - Label colour": "0.7 0.32 0.17 1",
"GUI - Off colour": "0.2 0.2 0.2 1",
"GUI - On colour": "0.7 0.32 0.17 1",
"Options - GUI Transparency 0-1": 0.9,
"Options - Plugin BlockList": ""
}

44
config/QuickSmelt.json Normal file
View File

@ -0,0 +1,44 @@
{
"Use Permission": true,
"Speed Multipliers": {
"global": 1.0,
"furnace.shortname": 1.0
},
"Fuel Usage Speed Multipliers": {
"global": 1.0,
"furnace.shortname": 1.0
},
"Fuel Usage Multipliers": {
"global": 1,
"furnace.shortname": 1
},
"Output Multipliers": {
"global": {
"global": 1.0
},
"furnace.shortname": {
"item.shortname": 1.0
}
},
"Whitelist": {
"global": [
"item.shortname"
],
"furnace.shortname": [
"item.shortname"
]
},
"Blacklist": {
"global": [
"item.shortname"
],
"furnace.shortname": [
"item.shortname"
]
},
"Smelting Frequencies (Smelt items every N smelting ticks)": {
"global": 1,
"furnace.shortname": 1
},
"Debug": false
}

22
config/TimeOfDay.json Normal file
View File

@ -0,0 +1,22 @@
{
"DatePreset": {
"presetDay": 1,
"presetMonth": 1,
"presetYear": 2020,
"setPresetDate": false
},
"Settings": {
"authLevelCmds": 1,
"authLevelFreeze": 2,
"autoSkipDay": false,
"autoSkipNight": false,
"dayLength": 30,
"freezeDate": false,
"logAutoSkipConsole": true,
"nightLength": 30
},
"TimeFreeze": {
"freezeTimeOnload": false,
"timeToFreeze": 12.0
}
}

7
config/WipeKits.json Normal file
View File

@ -0,0 +1,7 @@
{
"Kit Names & Cooldowns - Cooldowns (minutes)": {
"kitname1": 5.0,
"kitname2": 5.0
},
"Use GUI Kits (true/false)": false
}

View File

@ -0,0 +1,5 @@
{
"ItemList": [
"flare"
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,685 @@
{
"version": 2279,
"AllItemsAvailable": {
"hat.wolf": "Wolf Headdress",
"fogmachine": "Fogger-3000",
"strobelight": "Strobe Light",
"kayak": "Kayak",
"minihelicopter.repair": "MC repair",
"scraptransportheli.repair": "ScrapTransportHeliRepair",
"ammo.grenadelauncher.buckshot": "40mm Shotgun Round",
"ammo.grenadelauncher.he": "40mm HE Grenade",
"ammo.grenadelauncher.smoke": "40mm Smoke Grenade",
"arrow.hv": "High Velocity Arrow",
"arrow.wooden": "Wooden Arrow",
"arrow.bone": "Bone Arrow",
"arrow.fire": "Fire Arrow",
"ammo.handmade.shell": "Handmade Shell",
"ammo.nailgun.nails": "Nailgun Nails",
"ammo.pistol": "Pistol Bullet",
"ammo.pistol.fire": "Incendiary Pistol Bullet",
"ammo.pistol.hv": "HV Pistol Ammo",
"ammo.rifle": "5.56 Rifle Ammo",
"ammo.rifle.explosive": "Explosive 5.56 Rifle Ammo",
"ammo.rifle.incendiary": "Incendiary 5.56 Rifle Ammo",
"ammo.rifle.hv": "HV 5.56 Rifle Ammo",
"ammo.rocket.basic": "Rocket",
"ammo.rocket.fire": "Incendiary Rocket",
"ammo.rocket.hv": "High Velocity Rocket",
"ammo.rocket.smoke": "Smoke Rocket WIP!!!!",
"ammo.shotgun": "12 Gauge Buckshot",
"ammo.shotgun.fire": "12 Gauge Incendiary Shell",
"ammo.shotgun.slug": "12 Gauge Slug",
"door.double.hinged.metal": "Sheet Metal Double Door",
"door.double.hinged.toptier": "Armored Double Door",
"door.double.hinged.wood": "Wood Double Door",
"door.hinged.metal": "Sheet Metal Door",
"door.hinged.toptier": "Armored Door",
"door.hinged.wood": "Wooden Door",
"floor.grill": "Floor grill",
"floor.ladder.hatch": "Ladder Hatch",
"floor.triangle.grill": "Floor triangle grill",
"floor.triangle.ladder.hatch": "Triangle Ladder Hatch",
"gates.external.high.stone": "High External Stone Gate",
"gates.external.high.wood": "High External Wooden Gate",
"ladder.wooden.wall": "Wooden Ladder",
"wall.external.high.stone": "High External Stone Wall",
"wall.external.high": "High External Wooden Wall",
"wall.frame.cell.gate": "Prison Cell Gate",
"wall.frame.cell": "Prison Cell Wall",
"wall.frame.fence.gate": "Chainlink Fence Gate",
"wall.frame.fence": "Chainlink Fence",
"wall.frame.garagedoor": "Garage Door",
"wall.frame.netting": "Netting",
"wall.frame.shopfront": "Shop Front",
"wall.frame.shopfront.metal": "Metal Shop Front",
"wall.window.bars.metal": "Metal Window Bars",
"wall.window.bars.toptier": "Reinforced Glass Window",
"wall.window.bars.wood": "Wooden Window Bars",
"shutter.metal.embrasure.a": "Metal horizontal embrasure",
"shutter.metal.embrasure.b": "Metal Vertical embrasure",
"wall.window.glass.reinforced": "Strengthened Glass Window",
"shutter.wood.a": "Wood Shutters",
"watchtower.wood": "Watch Tower",
"diving.fins": "Diving Fins",
"diving.mask": "Diving Mask",
"diving.tank": "Diving Tank",
"diving.wetsuit": "Wetsuit",
"boots.frog": "Frog Boots",
"barrelcostume": "A Barrel Costume",
"cratecostume": "Crate Costume",
"burlap.gloves.new": "Burlap Gloves",
"burlap.gloves": "Leather Gloves",
"roadsign.gloves": "Roadsign Gloves",
"tactical.gloves": "Tactical Gloves",
"ghostsheet": "Ghost Costume",
"halloween.mummysuit": "Mummy Suit",
"scarecrow.suit": "Scarecrow Suit",
"scarecrowhead": "Scarecrow Wrap",
"attire.hide.helterneck": "Hide Halterneck",
"hat.beenie": "Beenie Hat",
"hat.boonie": "Boonie Hat",
"bucket.helmet": "Bucket Helmet",
"burlap.headwrap": "Burlap Headwrap",
"hat.candle": "Candle Hat",
"hat.cap": "Baseball Cap",
"clatter.helmet": "Clatter Helmet",
"coffeecan.helmet": "Coffee Can Helmet",
"deer.skull.mask": "Bone Helmet",
"heavy.plate.helmet": "Heavy Plate Helmet",
"hat.miner": "Miners Hat",
"partyhat": "Party Hat",
"riot.helmet": "Riot Helmet",
"wood.armor.helmet": "Wood Armor Helmet",
"hoodie": "Hoodie",
"bone.armor.suit": "Bone Armor",
"heavy.plate.jacket": "Heavy Plate Jacket",
"jacket.snow": "Snow Jacket",
"jacket": "Jacket",
"wood.armor.jacket": "Wood Chestplate",
"mask.balaclava": "Improvised Balaclava",
"mask.bandana": "Bandana Mask",
"metal.facemask": "Metal Facemask",
"nightvisiongoggles": "Night Vision Goggles",
"burlap.trousers": "Burlap Trousers",
"heavy.plate.pants": "Heavy Plate Pants",
"attire.hide.pants": "Hide Pants",
"roadsign.kilt": "Road Sign Kilt",
"pants.shorts": "Shorts",
"wood.armor.pants": "Wood Armor Pants",
"pants": "Pants",
"attire.hide.poncho": "Hide Poncho",
"burlap.shirt": "Burlap Shirt",
"shirt.collared": "Shirt",
"attire.hide.vest": "Hide Vest",
"shirt.tanktop": "Tank Top",
"shoes.boots": "Boots",
"burlap.shoes": "Burlap Shoes",
"attire.hide.boots": "Hide Boots",
"attire.hide.skirt": "Hide Skirt",
"attire.banditguard": "Bandit Guard Gear",
"hazmatsuit": "Hazmat Suit",
"hazmatsuit_scientist": "Scientist Suit",
"hazmatsuit_scientist_peacekeeper": "Scientist Suit",
"hazmatsuit.spacesuit": "Space Suit",
"scientistsuit_heavy": "Heavy Scientist Suit",
"tshirt.long": "Longsleeve T-Shirt",
"tshirt": "T-Shirt",
"metal.plate.torso": "Metal Chest Plate",
"roadsign.jacket": "Road Sign Jacket",
"bleach": "Bleach",
"ducttape": "Duct Tape",
"carburetor1": "Low Quality Carburetor",
"carburetor2": "Medium Quality Carburetor",
"carburetor3": "High Quality Carburetor",
"crankshaft1": "Low Quality Crankshaft",
"crankshaft2": "Medium Quality Crankshaft",
"crankshaft3": "High Quality Crankshaft",
"piston1": "Low Quality Pistons",
"piston2": "Medium Quality Pistons",
"piston3": "High Quality Pistons",
"sparkplug1": "Low Quality Spark Plugs",
"sparkplug2": "Medium Quality Spark Plugs",
"sparkplug3": "High Quality Spark Plugs",
"valve1": "Low Quality Valves",
"valve2": "Medium Quality Valves",
"valve3": "High Quality Valves",
"fuse": "Electric Fuse",
"gears": "Gears",
"glue": "Glue",
"metalblade": "Metal Blade",
"metalpipe": "Metal Pipe",
"propanetank": "Empty Propane Tank",
"roadsigns": "Road Signs",
"rope": "Rope",
"sewingkit": "Sewing Kit",
"sheetmetal": "Sheet Metal",
"metalspring": "Metal Spring",
"sticks": "Sticks",
"tarp": "Tarp",
"techparts": "Tech Trash",
"riflebody": "Rifle Body",
"semibody": "Semi Automatic Body",
"smgbody": "SMG Body",
"barricade.concrete": "Concrete Barricade",
"barricade.wood.cover": "Wooden Barricade Cover",
"barricade.metal": "Metal Barricade",
"barricade.sandbags": "Sandbag Barricade",
"barricade.stone": "Stone Barricade",
"barricade.wood": "Wooden Barricade",
"barricade.woodwire": "Barbed Wooden Barricade",
"bbq": "Barbeque",
"trap.bear": "Snap Trap",
"bed": "Bed",
"campfire": "Camp Fire",
"ceilinglight": "Ceiling Light",
"chair": "Chair",
"composter": "Composter",
"computerstation": "Computer Station",
"drone": "Drone",
"dropbox": "Drop Box",
"elevator": "Elevator",
"fireplace.stone": "Stone Fireplace",
"firework.boomer.blue": "Blue Boomer",
"firework.boomer.champagne": "Champagne Boomer",
"firework.boomer.green": "Green Boomer",
"firework.boomer.orange": "Orange Boomer",
"firework.boomer.red": "Red Boomer",
"firework.boomer.violet": "Violet Boomer",
"firework.romancandle.blue": "Blue Roman Candle",
"firework.romancandle.green": "Green Roman Candle",
"firework.romancandle.red": "Red Roman Candle",
"firework.romancandle.violet": "Violet Roman Candle",
"firework.volcano": "White Volcano Firework",
"firework.volcano.red": "Red Volcano Firework",
"firework.volcano.violet": "Violet Volcano Firework",
"spikes.floor": "Wooden Floor Spikes",
"fridge": "Fridge",
"furnace.large": "Large Furnace",
"furnace": "Furnace",
"hitchtroughcombo": "Hitch & Trough",
"habrepair": "Hab Repair",
"jackolantern.angry": "Jack O Lantern Angry",
"jackolantern.happy": "Jack O Lantern Happy",
"trap.landmine": "Land Mine",
"lantern": "Lantern",
"box.wooden.large": "Large Wood Box",
"water.barrel": "Water Barrel",
"locker": "Locker",
"mailbox": "Mail Box",
"mixingtable": "Mixing Table",
"modularcarlift": "Modular Car Lift",
"mining.pumpjack": "Pump Jack",
"small.oil.refinery": "Small Oil Refinery",
"planter.large": "Large Planter Box",
"planter.small": "Small Planter Box",
"electric.audioalarm": "Audio Alarm",
"smart.alarm": "Smart Alarm",
"smart.switch": "Smart Switch",
"storage.monitor": "Storage Monitor",
"electric.battery.rechargable.large": "Large Rechargable Battery",
"electric.battery.rechargable.medium": "Medium Rechargable Battery",
"electric.battery.rechargable.small": "Small Rechargable Battery",
"electric.button": "Button",
"electric.counter": "Counter",
"electric.hbhfsensor": "HBHF Sensor",
"electric.laserdetector": "Laser Detector",
"electric.pressurepad": "Pressure Pad",
"electric.doorcontroller": "Door Controller",
"electric.heater": "Electric Heater",
"fluid.combiner": "Fluid Combiner",
"fluid.splitter": "Fluid Splitter",
"fluid.switch": "Fluid Switch & Pump",
"electric.andswitch": "AND Switch",
"electric.blocker": "Blocker",
"electrical.branch": "Electrical Branch",
"electrical.combiner": "Root Combiner",
"electrical.memorycell": "Memory Cell",
"electric.orswitch": "OR Switch",
"electric.random.switch": "RAND Switch",
"electric.rf.broadcaster": "RF Broadcaster",
"electric.rf.receiver": "RF Receiver",
"electric.xorswitch": "XOR Switch",
"electric.fuelgenerator.small": "Small Generator",
"electric.generator.small": "Test Generator",
"electric.solarpanel.large": "Large Solar Panel",
"electric.igniter": "Igniter",
"electric.flasherlight": "Flasher Light",
"electric.simplelight": "Simple Light",
"electric.sirenlight": "Siren Light",
"powered.water.purifier": "Powered Water Purifier",
"electric.switch": "Switch",
"electric.splitter": "Splitter",
"electric.sprinkler": "Sprinkler",
"electric.teslacoil": "Tesla Coil",
"electric.timer": "Timer",
"electric.cabletunnel": "Cable Tunnel",
"waterpump": "Water Pump",
"mining.quarry": "Mining Quarry",
"target.reactive": "Reactive Target",
"box.repair.bench": "Repair Bench",
"research.table": "Research Table",
"rug.bear": "Rug Bear Skin",
"rug": "Rug",
"searchlight": "Search Light",
"secretlabchair": "Secret Lab Chair",
"shelves": "Salvaged Shelves",
"sign.hanging.banner.large": "Large Banner Hanging",
"sign.hanging": "Two Sided Hanging Sign",
"sign.hanging.ornate": "Two Sided Ornate Hanging Sign",
"sign.pictureframe.landscape": "Landscape Picture Frame",
"sign.pictureframe.portrait": "Portrait Picture Frame",
"sign.pictureframe.tall": "Tall Picture Frame",
"sign.pictureframe.xl": "XL Picture Frame",
"sign.pictureframe.xxl": "XXL Picture Frame",
"sign.pole.banner.large": "Large Banner on pole",
"sign.post.double": "Double Sign Post",
"sign.post.single": "Single Sign Post",
"sign.post.town": "One Sided Town Sign Post",
"sign.post.town.roof": "Two Sided Town Sign Post",
"sign.wooden.huge": "Huge Wooden Sign",
"sign.wooden.large": "Large Wooden Sign",
"sign.wooden.medium": "Medium Wooden Sign",
"sign.wooden.small": "Small Wooden Sign",
"guntrap": "Shotgun Trap",
"sleepingbag": "Sleeping Bag",
"stash.small": "Small Stash",
"sofa": "Sofa",
"spinner.wheel": "Spinning wheel",
"fishtrap.small": "Survival Fish Trap",
"table": "Table",
"workbench1": "Work Bench Level 1",
"workbench2": "Work Bench Level 2",
"workbench3": "Work Bench Level 3",
"cupboard.tool": "Tool Cupboard",
"tunalight": "Tuna Can Lamp",
"vending.machine": "Vending Machine",
"water.catcher.large": "Large Water Catcher",
"water.catcher.small": "Small Water Catcher",
"water.purifier": "Water Purifier",
"generator.wind.scrap": "Wind Turbine",
"box.wooden": "Wood Storage Box",
"apple": "Apple",
"apple.spoiled": "Rotten Apple",
"black.raspberries": "Black Raspberries",
"blueberries": "Blueberries",
"botabag": "Bota Bag",
"cactusflesh": "Cactus Flesh",
"can.beans": "Can of Beans",
"can.tuna": "Can of Tuna",
"chocholate": "Chocolate Bar",
"fish.cooked": "Cooked Fish",
"fish.raw": "Raw Fish",
"fish.minnows": "Minnows",
"fish.troutsmall": "Small Trout",
"granolabar": "Granola Bar",
"chicken.burned": "Burnt Chicken",
"chicken.cooked": "Cooked Chicken",
"chicken.raw": "Raw Chicken Breast",
"chicken.spoiled": "Spoiled Chicken",
"deermeat.burned": "Burnt Deer Meat",
"deermeat.cooked": "Cooked Deer Meat",
"deermeat.raw": "Raw Deer Meat",
"horsemeat.burned": "Burnt Horse Meat",
"horsemeat.cooked": "Cooked Horse Meat",
"horsemeat.raw": "Raw Horse Meat",
"humanmeat.burned": "Burnt Human Meat",
"humanmeat.cooked": "Cooked Human Meat",
"humanmeat.raw": "Raw Human Meat",
"humanmeat.spoiled": "Spoiled Human Meat",
"bearmeat.burned": "Burnt Bear Meat",
"bearmeat.cooked": "Cooked Bear Meat",
"bearmeat": "Raw Bear Meat",
"wolfmeat.burned": "Burnt Wolf Meat",
"wolfmeat.cooked": "Cooked Wolf Meat",
"wolfmeat.raw": "Raw Wolf Meat",
"wolfmeat.spoiled": "Spoiled Wolf Meat",
"meat.pork.burned": "Burnt Pork",
"meat.pork.cooked": "Cooked Pork",
"meat.boar": "Raw Pork",
"mushroom": "Mushroom",
"jar.pickle": "Pickles",
"smallwaterbottle": "Small Water Bottle",
"waterjug": "Water Jug",
"fun.bass": "Shovel Bass",
"fun.cowbell": "Cowbell",
"drumkit": "Junkyard Drum Kit",
"fun.flute": "Pan Flute",
"fun.guitar": "Acoustic Guitar",
"fun.jerrycanguitar": "Jerry Can Guitar",
"piano": "Wheelbarrow Piano",
"fun.tambourine": "Canbourine",
"fun.trumpet": "Plumber's Trumpet",
"fun.tuba": "Sousaphone",
"xylophone": "Xylobone",
"car.key": "Car Key",
"door.key": "Door Key",
"lock.key": "Key Lock",
"lock.code": "Code Lock",
"blueprintbase": "Blueprint",
"chineselantern": "Chinese Lantern",
"dragondoorknocker": "Dragon Door Knocker",
"hat.dragonmask": "Dragon Mask",
"newyeargong": "New Year Gong",
"hat.oxmask": "Ox Mask",
"hat.ratmask": "Rat Mask",
"lunar.firecrackers": "Firecracker String",
"arcade.machine.chippy": "Chippy Arcade Game",
"door.closer": "Door Closer",
"attire.bunnyears": "Bunny Ears",
"attire.bunny.onesie": "Bunny Onesie",
"easterdoorwreath": "Easter Door Wreath",
"easterbasket": "Egg Basket",
"rustige_egg_a": "Rustigé Egg - Red",
"rustige_egg_b": "Rustigé Egg - Blue",
"rustige_egg_c": "Rustigé Egg - Purple",
"rustige_egg_d": "Rustigé Egg - Ivory",
"attire.nesthat": "Nest Hat",
"easter.bronzeegg": "Bronze Egg",
"easter.goldegg": "Gold Egg",
"easter.paintedeggs": "Painted Egg",
"easter.silveregg": "Silver Egg",
"halloween.candy": "Halloween Candy",
"largecandles": "Large Candle Set",
"smallcandles": "Small Candle Set",
"coffin.storage": "Coffin",
"cursedcauldron": "Cursed Cauldron",
"gravestone": "Gravestone",
"woodcross": "Wooden Cross",
"wall.graveyard.fence": "Graveyard Fence",
"halloween.lootbag.large": "Large Loot Bag",
"halloween.lootbag.medium": "Medium Loot Bag",
"halloween.lootbag.small": "Small Loot Bag",
"pumpkinbasket": "Pumpkin Bucket",
"scarecrow": "Scarecrow",
"skullspikes.candles": "Skull Spikes",
"skullspikes.pumpkin": "Skull Spikes",
"skullspikes": "Skull Spikes",
"skulldoorknocker": "Skull Door Knocker",
"skull_fire_pit": "Skull Fire Pit",
"spiderweb": "Spider Webs",
"spookyspeaker": "Spooky Speaker",
"halloween.surgeonsuit": "Surgeon Scrubs",
"skull.trophy.jar": "Skull Trophy",
"skull.trophy.jar2": "Skull Trophy",
"skull.trophy.table": "Skull Trophy",
"skull.trophy": "Skull Trophy",
"movembermoustachecard": "Card Movember Moustache",
"movembermoustache": "Movember Moustache",
"note": "Note",
"skull.human": "Human Skull",
"abovegroundpool": "Above Ground Pool",
"beachchair": "Beach Chair",
"beachparasol": "Beach Parasol",
"beachtable": "Beach Table",
"beachtowel": "Beach Towel",
"boogieboard": "Boogie Board",
"innertube": "Inner Tube",
"innertube.horse": "Inner Tube",
"innertube.unicorn": "Inner Tube",
"tool.instant_camera": "Instant Camera",
"paddlingpool": "Paddling Pool",
"photo": "Photograph",
"photoframe.landscape": "Landscape Photo Frame",
"photoframe.large": "Large Photo Frame",
"photoframe.portrait": "Portrait Photo Frame",
"sunglasses02black": "Sunglasses",
"sunglasses02camo": "Sunglasses",
"sunglasses02red": "Sunglasses",
"sunglasses03black": "Sunglasses",
"sunglasses03chrome": "Sunglasses",
"sunglasses03gold": "Sunglasses",
"sunglasses": "Sunglasses",
"gun.water": "Water Gun",
"pistol.water": "Water Pistol",
"twitchsunglasses": "Purple Sunglasses",
"twitch.headset": "Headset",
"hobobarrel": "Hobo Barrel",
"door.hinged.industrial.a": "Industrial Door",
"candycaneclub": "Candy Cane Club",
"xmas.lightstring": "Christmas Lights",
"xmas.door.garland": "Festive Doorway Garland",
"candycane": "Candy Cane",
"giantcandycanedecor": "Giant Candy Decor",
"wall.ice.wall": "Short Ice Wall",
"wall.external.high.ice": "High Ice Wall",
"giantlollipops": "Giant Lollipop Decor",
"sign.neon.125x125": "Small Neon Sign",
"sign.neon.125x215.animated": "Medium Animated Neon Sign",
"sign.neon.125x215": "Medium Neon Sign",
"sign.neon.xl.animated": "Large Animated Neon Sign",
"sign.neon.xl": "Large Neon Sign",
"pookie.bear": "Pookie Bear",
"xmas.lightstring.advanced": "Deluxe Christmas Lights",
"coal": "Coal :(",
"xmas.present.large": "Large Present",
"xmas.present.medium": "Medium Present",
"xmas.present.small": "Small Present",
"sled.xmas": "Sled",
"sled": "Sled",
"snowmachine": "Snow Machine",
"snowball": "Snowball",
"ammo.snowballgun": "",
"snowballgun": "Snowball Gun",
"snowman": "Snowman",
"stocking.large": "SUPER Stocking",
"stocking.small": "Small Stocking",
"attire.reindeer.headband": "Reindeer Antlers",
"santabeard": "Santa Beard",
"santahat": "Santa Hat",
"xmas.window.garland": "Festive Window Garland",
"wrappedgift": "Wrapped Gift",
"wrappingpaper": "Wrapping Paper",
"xmasdoorwreath": "Christmas Door Wreath",
"xmas.decoration.baubels": "Decorative Baubels",
"xmas.decoration.candycanes": "Decorative Plastic Candy Canes",
"xmas.decoration.gingerbreadmen": "Decorative Gingerbread Men",
"xmas.decoration.lights": "Tree Lights",
"xmas.decoration.pinecone": "Decorative Pinecones",
"xmas.decoration.star": "Star Tree Topper",
"xmas.decoration.tinsel": "Decorative Tinsel",
"xmas.tree": "Christmas Tree",
"autoturret": "Auto Turret",
"flameturret": "Flame Turret",
"gloweyes": "Glowing Eyes",
"ammo.rocket.sam": "SAM Ammo",
"samsite": "SAM Site",
"black.berry": "Black Berry",
"clone.black.berry": "Black Berry Clone",
"seed.black.berry": "Black Berry Seed",
"blue.berry": "Blue Berry",
"clone.blue.berry": "Blue Berry Clone",
"seed.blue.berry": "Blue Berry Seed",
"green.berry": "Green Berry",
"clone.green.berry": "Green Berry Clone",
"seed.green.berry": "Green Berry Seed",
"red.berry": "Red Berry",
"clone.red.berry": "Red Berry Clone",
"seed.red.berry": "Red Berry Seed",
"white.berry": "White Berry",
"clone.white.berry": "White Berry Clone",
"seed.white.berry": "White Berry Seed",
"yellow.berry": "Yellow Berry",
"clone.yellow.berry": "Yellow Berry Clone",
"seed.yellow.berry": "Yellow Berry Seed",
"corn": "Corn",
"clone.corn": "Corn Clone",
"seed.corn": "Corn Seed",
"clone.hemp": "Hemp Clone",
"seed.hemp": "Hemp Seed",
"potato": "Potato",
"clone.potato": "Potato Clone",
"seed.potato": "Potato Seed",
"pumpkin": "Pumpkin",
"clone.pumpkin": "Pumpkin Plant Clone",
"seed.pumpkin": "Pumpkin Seed",
"fat.animal": "Animal Fat",
"battery.small": "Battery - Small",
"blood": "Blood",
"bone.fragments": "Bone Fragments",
"cctv.camera": "CCTV Camera",
"charcoal": "Charcoal",
"cloth": "Cloth",
"crude.oil": "Crude Oil",
"diesel_barrel": "Diesel Fuel",
"can.beans.empty": "Empty Can Of Beans",
"can.tuna.empty": "Empty Tuna Can",
"explosives": "Explosives",
"fertilizer": "Fertilizer",
"gunpowder": "Gun Powder",
"horsedung": "Horse Dung",
"hq.metal.ore": "High Quality Metal Ore",
"metal.refined": "High Quality Metal",
"leather": "Leather",
"lowgradefuel": "Low Grade Fuel",
"metal.fragments": "Metal Fragments",
"metal.ore": "Metal Ore",
"paper": "Paper",
"plantfiber": "Plant Fiber",
"researchpaper": "Research Paper",
"water.salt": "Salt Water",
"scrap": "Scrap",
"stones": "Stones",
"sulfur.ore": "Sulfur Ore",
"sulfur": "Sulfur",
"targeting.computer": "Targeting Computer",
"water": "Water",
"skull.wolf": "Wolf Skull",
"wood": "Wood",
"healingtea.advanced": "Advanced Healing Tea",
"healingtea": "Basic Healing Tea",
"healingtea.pure": "Pure Healing Tea",
"maxhealthtea.advanced": "Advanced Max Health Tea",
"maxhealthtea": "Basic Max Health Tea",
"maxhealthtea.pure": "Pure Max Health Tea",
"oretea.advanced": "Advanced Ore Tea",
"oretea": "Basic Ore Tea",
"oretea.pure": "Pure Ore Tea",
"radiationremovetea.advanced": "Advanced Rad. Removal Tea",
"radiationremovetea": "Rad. Removal Tea",
"radiationremovetea.pure": "Pure Rad. Removal Tea",
"radiationresisttea.advanced": "Adv. Anti-Rad Tea",
"radiationresisttea": "Anti-Rad Tea",
"radiationresisttea.pure": "Pure Anti-Rad Tea",
"scraptea.advanced": "Advanced Scrap Tea",
"scraptea": "Basic Scrap Tea",
"scraptea.pure": "Pure Scrap Tea",
"woodtea.advanced": "Advanced Wood Tea",
"woodtea": "Basic Wood Tea",
"woodtea.pure": "Pure Wood Tea",
"antiradpills": "Anti-Radiation Pills",
"tool.binoculars": "Binoculars",
"explosive.timed": "Timed Explosive Charge",
"tool.camera": "Camera",
"rf.detonator": "RF Transmitter",
"fishingrod.handmade": "Handmade Fishing Rod",
"flare": "Flare",
"flashlight.held": "Flashlight",
"geiger.counter": "Geiger Counter",
"hosetool": "Hose Tool",
"jackhammer": "Jackhammer",
"keycard_blue": "Blue Keycard",
"keycard_green": "Green Keycard",
"keycard_red": "Red Keycard",
"largemedkit": "Large Medkit",
"map": "Paper Map",
"syringe.medical": "Medical Syringe",
"rf_pager": "RF Pager",
"building.planner": "Building Plan",
"grenade.smoke": "Smoke Grenade",
"supply.signal": "Supply Signal",
"surveycharge": "Survey Charge",
"wiretool": "Wire Tool",
"vehicle.chassis.2mod": "Small Chassis",
"vehicle.chassis.3mod": "Medium Chassis",
"vehicle.chassis.4mod": "Large Chassis",
"vehicle.chassis": "Generic vehicle chassis",
"vehicle.1mod.cockpit": "Cockpit Vehicle Module",
"vehicle.1mod.cockpit.armored": "Armored Cockpit Vehicle Module",
"vehicle.1mod.cockpit.with.engine": "Cockpit With Engine Vehicle Module",
"vehicle.1mod.engine": "Engine Vehicle Module",
"vehicle.1mod.flatbed": "Flatbed Vehicle Module",
"vehicle.1mod.passengers.armored": "Armored Passenger Vehicle Module",
"vehicle.1mod.rear.seats": "Rear Seats Vehicle Module",
"vehicle.1mod.storage": "Storage Vehicle Module",
"vehicle.1mod.taxi": "Taxi Vehicle Module",
"vehicle.2mod.flatbed": "Large Flatbed Vehicle Module",
"vehicle.2mod.fuel.tank": "Fuel Tank Vehicle Module",
"vehicle.2mod.passengers": "Passenger Vehicle Module",
"vehicle.module": "Generic vehicle module",
"telephone": "Telephone",
"weapon.mod.8x.scope": "16x Zoom Scope",
"weapon.mod.flashlight": "Weapon flashlight",
"weapon.mod.holosight": "Holosight",
"weapon.mod.lasersight": "Weapon Lasersight",
"weapon.mod.muzzleboost": "Muzzle Boost",
"weapon.mod.muzzlebrake": "Muzzle Brake",
"weapon.mod.simplesight": "Simple Handmade Sight",
"weapon.mod.silencer": "Silencer",
"weapon.mod.small.scope": "8x Zoom Scope",
"rifle.ak": "Assault Rifle",
"bandage": "Bandage",
"grenade.beancan": "Beancan Grenade",
"rifle.bolt": "Bolt Action Rifle",
"bone.club": "Bone Club",
"knife.bone": "Bone Knife",
"bow.hunting": "Hunting Bow",
"cakefiveyear": "Birthday Cake",
"chainsaw": "Chainsaw",
"salvaged.cleaver": "Salvaged Cleaver",
"bow.compound": "Compound Bow",
"crossbow": "Crossbow",
"shotgun.double": "Double Barrel Shotgun",
"pistol.eoka": "Eoka Pistol",
"grenade.f1": "F1 Grenade",
"flamethrower": "Flame Thrower",
"multiplegrenadelauncher": "Multiple Grenade Launcher",
"knife.butcher": "Butcher Knife",
"pitchfork": "Pitchfork",
"sickle": "Sickle",
"hammer": "Hammer",
"hatchet": "Hatchet",
"knife.combat": "Combat Knife",
"rifle.l96": "L96 Rifle",
"rifle.lr300": "LR-300 Assault Rifle",
"lmg.m249": "M249",
"rifle.m39": "M39 Rifle",
"pistol.m92": "M92 Pistol",
"mace": "Mace",
"machete": "Machete",
"smg.mp5": "MP5A4",
"pistol.nailgun": "Nailgun",
"paddle": "Paddle",
"pickaxe": "Pickaxe",
"shotgun.waterpipe": "Waterpipe Shotgun",
"pistol.python": "Python Revolver",
"pistol.revolver": "Revolver",
"rock": "Rock",
"rocket.launcher": "Rocket Launcher",
"axe.salvaged": "Salvaged Axe",
"hammer.salvaged": "Salvaged Hammer",
"icepick.salvaged": "Salvaged Icepick",
"explosive.satchel": "Satchel Charge",
"shotgun.pump": "Pump Shotgun",
"pistol.semiauto": "Semi-Automatic Pistol",
"rifle.semiauto": "Semi-Automatic Rifle",
"smg.2": "Custom SMG",
"shotgun.spas12": "Spas-12 Shotgun",
"stonehatchet": "Stone Hatchet",
"stone.pickaxe": "Stone Pickaxe",
"spear.stone": "Stone Spear",
"longsword": "Longsword",
"salvaged.sword": "Salvaged Sword",
"smg.thompson": "Thompson",
"toolgun": "Garry's Mod Tool Gun",
"torch": "Torch",
"bucket.water": "Water Bucket",
"spear.wooden": "Wooden Spear",
"horse.armor.roadsign": "Roadsign Horse Armor",
"horse.armor.wood": "Wooden Horse Armor",
"horse.saddle": "Horse Saddle",
"horse.saddlebag": "Saddle bag",
"horse.shoes.advanced": "High Quality Horse Shoes",
"horse.shoes.basic": "Basic Horse Shoes"
}
}

3
data/Kits.json Normal file
View File

@ -0,0 +1,3 @@
{
"Kits": {}
}

1
data/Kits_Data.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,6 @@
-
76561198106966240ŕńůĹ<C5AF>€€<E282AC> Sick Prodigy
+
76561198017312452Äí™<E284A2>€€<E282AC>
Dunkeykong

BIN
data/oxide.groups.data Normal file

Binary file not shown.

4
data/oxide.lang.data Normal file
View File

@ -0,0 +1,4 @@
en
76561198106966240en
76561198017312452en

8
data/oxide.users.data Normal file
View File

@ -0,0 +1,8 @@
3
76561198106966240
default
admin Sick Prodigy
'
76561198017312452
defaultUnnamed

View File

@ -0,0 +1,27 @@
{
"NoInvSpace": "You don't have enough room to craft this item!",
"NoPerms": "You don't have permission to use this command.",
"CannotFindItem": "Cannot find item {0}.",
"ItemBlocked": "{0} has been blocked from crafting.",
"ItemUnblocked": "{0} has been unblocked from crafting.",
"NeedsAdvancedOptions": "You need to enable advanced crafting options in your config to use this.",
"WrongNumberInput": "Your input needs to be a number.",
"ItemCraftTimeSet": "{0} craft time set to {1} seconds",
"WorkbenchLevelSet": "{0} workbench level set to {1}",
"CurrentCraftinRate": "The current crafting rate is {0 }%",
"CraftingRateUpdated": "The crafting rate was updated to {0} %",
"CraftTime2Args": "This command needs two arguments in the format /crafttime item.shortname timetocraft",
"BlockItem1Args": "This command needs one argument in the format /blockitem item.shortname",
"UnblockItem1Args": "This command needs one argument in the format /unblockitem item.shortname",
"WorckBenchLvl2Args": "This command needs two arguments in the format /benchlvl item.shortname workbenchlvl",
"BenchLevelInput": "The work bench level must be between 0 and 3",
"SetSkin2Args": "This command needs one argument in the format /setcraftskin item.shortname skinworkshopid",
"SkinSet": "The default skin for {0} was set to {1}",
"CraftTimeCheck": "The craft time of this item is {0}",
"CommandCraftingRate": "craftrate",
"CommandCraftTime": "crafttime",
"CommandBlockItem": "blockitem",
"CommandUnblockItem": "unblockitem",
"CommandWorkbenchLVL": "benchlvl",
"CommandSetDefaultSkin": "setcraftskin"
}

33
lang/en/Kits.json Normal file
View File

@ -0,0 +1,33 @@
{
"title": "Kits: ",
"Name": "Name",
"Description": "Description",
"Redeem": "Redeem",
"AddKit": "Add Kit",
"Close": "Close",
"NoKitsFound": "All Available Kits are already in this Menu!",
"AddKitToMenu": "Select a Kit to Add to this Menu",
"KitCooldown": "Cooldown: {0}",
"Unavailable": "Unavailable",
"Last": "Last",
"Next": "Next",
"Back": "Back",
"First": "First",
"RemoveKit": "Remove Kit?",
"KitUses": "Uses: {0}",
"NoInventorySpace": "You do not have enough inventory space for this Kit!",
"Unlimited": "Unlimited",
"None": "None",
"KitRedeemed": "Kit Redeemed",
"Emptykitname": "Empty Kit Name",
"KitExistError": "This kit doesn't exist",
"CantRedeemNow": "You are not allowed to redeem a kit at the moment",
"NoAuthToRedeem": "You don't have the Auth Level to use this kit",
"NoPermKit": "You don't have the permissions to use this kit",
"NoRemainingUses": "You already redeemed all of these kits",
"CooldownMessage": "You need to wait {0} seconds to use this kit",
"WipeCooldownMessage": "You need to wait {0} seconds to use this kit since it recently wiped",
"NPCError": "You must find the NPC that gives this kit to redeem it.",
"PastingError": "Something went wrong while pasting, is CopyPaste installed?",
"NoKitFound": "This kit doesn't exist"
}

View File

@ -0,0 +1,24 @@
{
"title": "Permissions Manager: ",
"NoGroup": "Group {0} was not found.",
"NoPlayer": "Player {0} was not found.",
"GUIAll": "Grant All",
"GUINone": "Revoke All",
"GUIBack": "Back",
"GUIGroups": "Groups",
"GUIPlayers": "Players",
"GUIInherited": "Inherited",
"GUIInheritedFrom": "Inherited from",
"GUIGranted": "Granted",
"GUIRevoked": "Revoked",
"GUIName": "Permissions for {0}",
"GUIGroupsFor": "Groups for {0}",
"GUIPlayersIn": "Players in {0}",
"removePlayers": "Remove All Players",
"confirm": "Confirm",
"cancel": "Cancel",
"NotAdmin": "You need Auth Level 2, or permission, to use this command.",
"Back": "Back",
"All": "All",
"Syntax": "Use /perms, /perms player *name*, or /perms group *name*"
}

67
lang/en/RustCore.json Normal file
View File

@ -0,0 +1,67 @@
{
"CommandUsageExtLoad": "Usage: oxide.ext.load <extname>+",
"CommandUsageExtUnload": "Usage: oxide.ext.unload <extname>+",
"CommandUsageExtReload": "Usage: oxide.ext.reload <extname>+",
"CommandUsageGrant": "Usage: oxide.grant <group|user> <name|id> <permission>",
"CommandUsageGroup": "Usage: oxide.group <add|set> <name> [title] [rank]",
"CommandUsageGroupParent": "Usage: oxide.group <parent> <name> <parentName>",
"CommandUsageGroupRemove": "Usage: oxide.group <remove> <name>",
"CommandUsageLang": "Usage: oxide.lang <two-digit language code>",
"CommandUsageLoad": "Usage: oxide.load *|<pluginname>+",
"CommandUsageReload": "Usage: oxide.reload *|<pluginname>+",
"CommandUsageRevoke": "Usage: oxide.revoke <group|user> <name|id> <permission>",
"CommandUsageShow": "Usage: oxide.show <groups|perms>",
"CommandUsageShowName": "Usage: oxide.show <group|user> <name>",
"CommandUsageUnload": "Usage: oxide.unload *|<pluginname>+",
"CommandUsageUserGroup": "Usage: oxide.usergroup <add|remove> <username> <groupname>",
"ConnectionRejected": "Connection was rejected",
"DataSaved": "Saving Oxide data...",
"GroupAlreadyExists": "Group '{0}' already exists",
"GroupAlreadyHasPermission": "Group '{0}' already has permission '{1}'",
"GroupDoesNotHavePermission": "Group '{0}' does not have permission '{1}'",
"GroupChanged": "Group '{0}' changed",
"GroupCreated": "Group '{0}' created",
"GroupDeleted": "Group '{0}' deleted",
"GroupNotFound": "Group '{0}' doesn't exist",
"GroupParentChanged": "Group '{0}' parent changed to '{1}'",
"GroupParentNotChanged": "Group '{0}' parent was not changed",
"GroupParentNotFound": "Group parent '{0}' doesn't exist",
"GroupPermissionGranted": "Group '{0}' granted permission '{1}'",
"GroupPermissionRevoked": "Group '{0}' revoked permission '{1}'",
"GroupPermissions": "Group '{0}' permissions",
"GroupPlayers": "Group '{0}' players",
"Groups": "Groups",
"NoGroupPermissions": "No permissions currently granted",
"NoPermissionGroups": "No groups with this permission",
"NoPermissionPlayers": "No players with this permission",
"NoPluginsFound": "No plugins are currently available",
"NoPlayerGroups": "Player is not assigned to any groups",
"NoPlayerPermissions": "No permissions currently granted",
"NoPlayersInGroup": "No players currently in group",
"NotAllowed": "You are not allowed to use the '{0}' command",
"ParentGroupPermissions": "Parent group '{0}' permissions",
"PermissionGroups": "Permission '{0}' Groups",
"PermissionPlayers": "Permission '{0}' Players",
"PermissionNotFound": "Permission '{0}' doesn't exist",
"Permissions": "Permissions",
"PermissionsNotLoaded": "Unable to load permission files! Permissions will not work until resolved.\n => {0}",
"PlayerLanguage": "Player language set to {0}",
"PluginNotLoaded": "Plugin '{0}' not loaded.",
"PluginReloaded": "Reloaded plugin {0} v{1} by {2}",
"PluginUnloaded": "Unloaded plugin {0} v{1} by {2}",
"ServerLanguage": "Server language set to {0}",
"Unknown": "Unknown",
"UnknownCommand": "Unknown command: {0}",
"PlayerAddedToGroup": "Player '{0}' added to group: {1}",
"PlayerAlreadyHasPermission": "Player '{0}' already has permission '{1}'",
"PlayerDoesNotHavePermission": "Player '{0}' does not have permission '{1}'",
"PlayerNotFound": "Player '{0}' not found",
"PlayerGroups": "Player '{0}' groups",
"PlayerPermissions": "Player '{0}' permissions",
"PlayerPermissionGranted": "Player '{0}' granted permission '{1}'",
"PlayerPermissionRevoked": "Player '{0}' revoked permission '{1}'",
"PlayerRemovedFromGroup": "Player '{0}' removed from group '{1}'",
"PlayersFound": "Multiple players were found, please specify: {0}",
"Version": "Server is running [#ffb658]Oxide {0}[/#] and [#ee715c]{1} {2} ({3})[/#]",
"YouAreNotAdmin": "You are not an admin"
}

10
lang/en/WipeKits.json Normal file
View File

@ -0,0 +1,10 @@
{
"DayFormat": "<color=orange>{0}</color> day and <color=orange>{1}</color> hours",
"DaysFormat": "<color=orange>{0}</color> days and <color=orange>{1}</color> hours",
"HourFormat": "<color=orange>{0}</color> hour and <color=orange>{1}</color> minutes",
"HoursFormat": "<color=orange>{0}</color> hours and <color=orange>{1}</color> minutes",
"MinFormat": "<color=orange>{0}</color> minute and <color=orange>{1}</color> seconds",
"MinsFormat": "<color=orange>{0}</color> minutes and <color=orange>{1}</color> seconds",
"SecsFormat": "<color=orange>{0}</color> seconds",
"CantUse": "The server's just wiped! Try again in {0}"
}

View File

@ -0,0 +1,12 @@
[SERVER v1.0.20] Started as service
[SERVER v1.0.20] Running as service
[SERVER v1.0.20] Got Message: Ready
[SERVER v1.0.20] Got Message: Compile
[SERVER v1.0.20] Console: PermissionsManager.cs(299,24): warning CS0219: The variable `granted' is assigned but its value is never used
PermissionsManager.cs(353,20): warning CS0219: The variable `guiString' is assigned but its value is never used
PermissionsManager.cs(384,20): warning CS0219: The variable `guiString' is assigned but its value is never used
[SERVER v1.0.20] Got Message: Exit
[SERVER v1.0.20] Exit received.
[SERVER v1.0.20] Connection closed.
[SERVER v1.0.20] Shutdown

244
logs/oxide_2021-02-08.txt Normal file
View File

@ -0,0 +1,244 @@
17:35 [Info] Loading Oxide Core v2.0.3991...
17:35 [Info] Loading extensions...
17:35 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
17:35 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
17:35 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
17:35 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
17:35 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
17:35 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
17:35 [Info] Local compiler MD5: 0
17:35 [Info] Compiler MD5 hash did not match, downloading latest
17:35 [Info] Downloading Compiler.x86_x64 for .cs (C#) plugin compilation
17:35 [Info] Local MD5 hash did not match remote MD5 hash for Compiler.x86_x64, attempting download again
17:35 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
17:35 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
17:35 [Info] Using Covalence provider for game 'Rust'
17:35 [Info] Loading plugins...
17:35 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
17:35 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
17:44 [Info] IP address from Steam query: 0.0.0.0
18:16 [Info] Loading Oxide Core v2.0.3991...
18:16 [Info] Loading extensions...
18:16 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
18:16 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
18:16 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
18:16 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
18:16 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
18:16 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
18:16 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
18:16 [Info] Using Covalence provider for game 'Rust'
18:16 [Info] Loading plugins...
18:16 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
18:16 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
18:25 [Info] IP address from Steam query: 0.0.0.0
19:00 [Info] Loading Oxide Core v2.0.3991...
19:00 [Info] Loading extensions...
19:00 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
19:00 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
19:00 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
19:00 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
19:00 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
19:00 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:00 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:00 [Info] Using Covalence provider for game 'Rust'
19:00 [Info] Loading plugins...
19:00 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
19:00 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
19:09 [Info] IP address from Steam query: 0.0.0.0
19:17 [Info] Loading Oxide Core v2.0.3991...
19:17 [Info] Loading extensions...
19:17 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
19:17 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
19:17 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
19:17 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
19:17 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
19:17 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:17 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:17 [Info] Using Covalence provider for game 'Rust'
19:17 [Info] Loading plugins...
19:17 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
19:17 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
19:19 [Info] Loading Oxide Core v2.0.3991...
19:19 [Info] Loading extensions...
19:19 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
19:19 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
19:19 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
19:19 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
19:19 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
19:19 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:19 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:19 [Info] Using Covalence provider for game 'Rust'
19:19 [Info] Loading plugins...
19:19 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
19:19 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
19:29 [Info] IP address from Steam query: 0.0.0.0
19:34 [Info] Loading Oxide Core v2.0.3991...
19:34 [Info] Loading extensions...
19:34 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
19:34 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
19:34 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
19:34 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
19:34 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
19:34 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:34 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:34 [Info] Using Covalence provider for game 'Rust'
19:34 [Info] Loading plugins...
19:34 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
19:34 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
19:43 [Info] IP address from Steam query: 0.0.0.0
19:51 [Info] Loading Oxide Core v2.0.3991...
19:51 [Info] Loading extensions...
19:51 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
19:51 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
19:51 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
19:51 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
19:51 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
19:51 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:51 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:51 [Info] Using Covalence provider for game 'Rust'
19:51 [Info] Loading plugins...
19:51 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
19:51 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
19:52 [Info] Loading Oxide Core v2.0.3991...
19:52 [Info] Loading extensions...
19:52 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
19:52 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
19:52 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
19:52 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
19:52 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
19:52 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:52 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
19:52 [Info] Using Covalence provider for game 'Rust'
19:52 [Info] Loading plugins...
19:52 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
19:52 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
20:02 [Info] IP address from Steam query: 0.0.0.0
20:10 [Info] Loading Oxide Core v2.0.3991...
20:10 [Info] Loading extensions...
20:10 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
20:10 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
20:10 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
20:10 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
20:10 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
20:10 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:10 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:10 [Info] Using Covalence provider for game 'Rust'
20:10 [Info] Loading plugins...
20:10 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
20:10 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
20:19 [Info] IP address from Steam query: 0.0.0.0
20:25 [Info] Loading Oxide Core v2.0.3991...
20:25 [Info] Loading extensions...
20:25 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
20:25 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
20:25 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
20:25 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
20:25 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
20:25 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:25 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:25 [Info] Using Covalence provider for game 'Rust'
20:25 [Info] Loading plugins...
20:25 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
20:25 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
20:29 [Info] Loading Oxide Core v2.0.3991...
20:29 [Info] Loading extensions...
20:29 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
20:29 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
20:29 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
20:29 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
20:29 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
20:29 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:29 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:29 [Info] Using Covalence provider for game 'Rust'
20:29 [Info] Loading plugins...
20:29 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
20:29 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
20:39 [Info] IP address from Steam query: 0.0.0.0
20:43 [Info] Loading Oxide Core v2.0.3991...
20:43 [Info] Loading extensions...
20:43 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
20:43 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
20:43 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
20:43 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
20:43 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
20:43 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:43 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
20:43 [Info] Using Covalence provider for game 'Rust'
20:43 [Info] Loading plugins...
20:43 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
20:43 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
20:53 [Info] IP address from Steam query: 0.0.0.0
20:59 [Info] GatherManager was compiled successfully in 3410ms
20:59 [Warning] [Gathering Manager] New configuration file created.
20:59 [Warning] [Gathering Manager] Configuration file updated.
20:59 [Warning] Calling 'OnServerInitialized' on 'GatherManager v2.2.75' took 169ms
20:59 [Info] Loaded plugin Gathering Manager v2.2.75 by Mughisi
21:00 [Error] Oxide.Ext.Discord is referenced by DiscordAuth plugin but is not loaded! An appropriate include file needs to be saved to plugins\include\Ext.Discord.cs if this extension is not required.
21:00 [Info] CraftingController was compiled successfully in 3310ms
21:00 [Info] Loaded plugin Crafting Controller v3.2.2 by Whispers88
21:00 [Info] TimeOfDay was compiled successfully in 3578ms
21:00 [Info] Loaded plugin TimeOfDay v2.3.4 by FuJiCuRa
21:00 [Info] QuickSmelt was compiled successfully in 540ms
21:00 [Warning] Calling 'OnServerInitialized' on 'QuickSmelt v5.1.3' took 174ms
21:00 [Info] Loaded plugin Quick Smelt v5.1.3 by Iv Misticos
21:01 [Info] BetterLoot was compiled successfully in 691ms
21:01 [Info] [BetterLoot] No Blacklist found, creating new file...
21:01 [Info] [BetterLoot] Using '33' active of '35' supported containertypes
21:01 [Info] [BetterLoot] Exported 680 items to 'NamesList'
21:01 [Info] [BetterLoot] Updating internals ...
21:01 [Info] Loaded plugin BetterLoot v3.5.3 by Default
21:01 [Info] [BetterLoot] Removed 7 stacked LootContainer
21:01 [Info] [BetterLoot] Populated '3512' supported containers.
21:02 [Info] WipeKits was compiled successfully in 2774ms
21:02 [Warning] [Wipe Kits] Loading default configuration file...
21:02 [Info] Loaded plugin Wipe Kits v1.2.51 by Ryan
21:02 [Info] Kits was compiled successfully in 3011ms
21:02 [Info] Loaded plugin Kits v3.3.1 by Reneb
21:03 [Info] Unloaded plugin Kits v3.3.1 by Reneb
21:03 [Info] Loaded plugin Kits v3.3.1 by Reneb
21:04 [Warning] Calling 'Unload' on 'GatherManager v2.2.75' took 160ms
21:04 [Info] Unloaded plugin Gathering Manager v2.2.75 by Mughisi
21:04 [Info] Unloaded plugin Crafting Controller v3.2.2 by Whispers88
21:04 [Info] Unloaded plugin TimeOfDay v2.3.4 by FuJiCuRa
21:04 [Warning] Calling 'Unload' on 'QuickSmelt v5.1.3' took 155ms
21:04 [Info] Unloaded plugin Quick Smelt v5.1.3 by Iv Misticos
21:04 [Warning] Calling 'Unload' on 'BetterLoot v3.5.3' took 156ms
21:04 [Info] Unloaded plugin BetterLoot v3.5.3 by Default
21:04 [Info] Unloaded plugin Wipe Kits v1.2.51 by Ryan
21:04 [Info] Unloaded plugin Kits v3.3.1 by Reneb
21:04 [Info] Loading Oxide Core v2.0.3991...
21:04 [Info] Loading extensions...
21:04 [Info] Loaded extension CSharp v2.0.4041 by Oxide Team and Contributors
21:04 [Info] Loaded extension MySql v2.0.3760 by Oxide Team and Contributors
21:04 [Info] Loaded extension Rust v2.0.4907 by Oxide Team and Contributors
21:04 [Info] Loaded extension SQLite v2.0.3762 by Oxide Team and Contributors
21:04 [Info] Loaded extension Unity v2.0.3772 by Oxide Team and Contributors
21:04 [Info] Latest compiler MD5: 8ce6d27e7718e3d164766bba8833537a
21:04 [Info] Local compiler MD5: 8ce6d27e7718e3d164766bba8833537a
21:04 [Info] Using Covalence provider for game 'Rust'
21:04 [Info] Loading plugins...
21:04 [Info] Loaded plugin Rust v2.0.4907 by Oxide Team and Contributors
21:04 [Info] Loaded plugin Unity v2.0.3772 by Oxide Team and Contributors
21:04 [Error] Oxide.Ext.Discord is referenced by DiscordAuth plugin but is not loaded! An appropriate include file needs to be saved to plugins\include\Ext.Discord.cs if this extension is not required.
21:04 [Info] BetterLoot, CraftingController, GatherManager, Kits, QuickSmelt, TimeOfDay and WipeKits were compiled successfully in 0ms
21:04 [Info] Loaded plugin BetterLoot v3.5.3 by Default
21:04 [Info] Loaded plugin Crafting Controller v3.2.2 by Whispers88
21:04 [Info] Loaded plugin Gathering Manager v2.2.75 by Mughisi
21:04 [Info] Loaded plugin Kits v3.3.1 by Reneb
21:04 [Info] Loaded plugin Quick Smelt v5.1.3 by Iv Misticos
21:04 [Info] Loaded plugin TimeOfDay v2.3.4 by FuJiCuRa
21:04 [Info] Loaded plugin Wipe Kits v1.2.51 by Ryan
21:14 [Info] IP address from Steam query: 0.0.0.0
21:14 [Info] [BetterLoot] Using '33' active of '35' supported containertypes
21:14 [Info] [BetterLoot] Updating internals ...
21:14 [Warning] Calling 'OnServerInitialized' on 'GatherManager v2.2.75' took 133ms
21:14 [Warning] Calling 'OnServerInitialized' on 'QuickSmelt v5.1.3' took 133ms
21:14 [Info] [BetterLoot] No stacked LootContainer found.
21:14 [Info] [BetterLoot] Populated '800' supported containers.
22:15 [Info] The current crafting rate is 50%
22:17 [Info] Groups:
default, admin
22:17 [Info] Player 'Sick Prodigy(76561198106966240)' added to group: admin
22:22 [Info] PermissionsManager was compiled successfully in 3149ms
22:22 [Info] [PermissionsManager] Creating new config file.
22:22 [Info] Loaded plugin PermissionsManager v2.0.4 by Steenamaroo

23
oxide.config.json Normal file
View File

@ -0,0 +1,23 @@
{
"Options": {
"Modded": true,
"PluginWatchers": true,
"DefaultGroups": {
"Players": "default",
"Moderators": "moderate"
"Administrators": "admin"
},
"WebRequestIP": "0.0.0.0"
},
"OxideConsole": {
"Enabled": true,
"MinimalistMode": true,
"ShowStatusBar": true
},
"OxideRcon": {
"Enabled": false,
"Port": 25580,
"Password": "",
"ChatPrefix": "[Server Console]"
}
}

1813
plugins/AdminLogger.cs Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1357
plugins/Backpacks.cs Normal file

File diff suppressed because it is too large Load Diff

953
plugins/BetterChat.cs Normal file
View File

@ -0,0 +1,953 @@
using Oxide.Plugins.BetterChatExtensions;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
using System;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
#if RUST
using Network;
using ConVar;
using Facepunch;
using Facepunch.Math;
using CompanionServer;
#endif
// TODO: Improve string usage by using stringbuilders
// TODO: Add "name" or "identifier" format for third-party plugins to obtain a formatted identifier
namespace Oxide.Plugins
{
[Info("Better Chat", "LaserHydra", "5.2.5")]
[Description("Allows to manage chat groups, customize colors and add titles.")]
internal class BetterChat : CovalencePlugin
{
#region Fields
private static BetterChat _instance;
private Configuration _config;
private List<ChatGroup> _chatGroups;
private Dictionary<Plugin, Func<IPlayer, string>> _thirdPartyTitles = new Dictionary<Plugin, Func<IPlayer, string>>();
private static readonly string[] _stringReplacements = new string[]
{
#if RUST || HURTWORLD || UNTURNED
"<b>", "</b>",
"<i>", "</i>",
"</size>",
"</color>"
#endif
};
private static readonly Regex[] _regexReplacements = new Regex[]
{
new Regex(@"<voffset=(?:.|\s)*?>", RegexOptions.Compiled),
#if RUST || HURTWORLD || UNTURNED
new Regex(@"<color=.+?>", RegexOptions.Compiled),
new Regex(@"<size=.+?>", RegexOptions.Compiled),
#elif REIGNOFKINGS || SEVENDAYSTODIE
new Regex(@"\[[\w\d]{6}\]", RegexOptions.Compiled),
#elif RUSTLEGACY
new Regex(@"\[color #[\w\d]{6}\]", RegexOptions.Compiled),
#elif TERRARIA
new Regex(@"\[c\/[\w\d]{6}:", RegexOptions.Compiled),
#endif
};
#endregion
#region Hooks
private void Loaded()
{
_instance = this;
LoadData(ref _chatGroups);
if (_chatGroups.Count == 0)
_chatGroups.Add(new ChatGroup("default"));
foreach (ChatGroup group in _chatGroups)
{
if (!permission.GroupExists(group.GroupName))
permission.CreateGroup(group.GroupName, string.Empty, 0);
}
SaveData(_chatGroups);
}
private void OnPluginUnloaded(Plugin plugin)
{
if (_thirdPartyTitles.ContainsKey(plugin))
_thirdPartyTitles.Remove(plugin);
}
#if RUST
private object OnPlayerChat(BasePlayer bplayer, string message, Chat.ChatChannel chatchannel)
{
IPlayer player = bplayer.IPlayer;
#else
private object OnUserChat(IPlayer player, string message)
{
#endif
if (message.Length > _instance._config.MaxMessageLength)
message = message.Substring(0, _instance._config.MaxMessageLength);
BetterChatMessage chatMessage = ChatGroup.FormatMessage(player, message);
if (chatMessage == null)
return null;
Dictionary<string, object> chatMessageDict = chatMessage.ToDictionary();
#if RUST
chatMessageDict.Add("ChatChannel", chatchannel);
#endif
foreach (Plugin plugin in plugins.GetAll())
{
object hookResult = plugin.CallHook("OnBetterChat", chatMessageDict);
if (hookResult is Dictionary<string, object>)
{
try
{
chatMessageDict = hookResult as Dictionary<string, object>;
}
catch (Exception e)
{
PrintError($"Failed to load modified OnBetterChat hook data from plugin '{plugin.Title} ({plugin.Version})':{Environment.NewLine}{e}");
continue;
}
}
else if (hookResult != null)
return null;
}
chatMessage = BetterChatMessage.FromDictionary(chatMessageDict);
switch (chatMessage.CancelOption)
{
case BetterChatMessage.CancelOptions.BetterChatOnly:
return null;
case BetterChatMessage.CancelOptions.BetterChatAndDefault:
return true;
}
var output = chatMessage.GetOutput();
#if RUST
switch (chatchannel)
{
case Chat.ChatChannel.Team:
RelationshipManager.PlayerTeam team = bplayer.Team;
if (team == null || team.members.Count == 0)
{
return true;
}
team.BroadcastTeamChat(bplayer.userID, player.Name, chatMessage.Message, chatMessage.UsernameSettings.Color);
List<Network.Connection> onlineMemberConnections = team.GetOnlineMemberConnections();
if (onlineMemberConnections != null)
{
ConsoleNetwork.SendClientCommand(onlineMemberConnections, "chat.add", new object[] { (int) chatchannel, player.Id, output.Chat });
}
break;
default:
foreach (BasePlayer p in BasePlayer.activePlayerList.Where(p => !chatMessage.BlockedReceivers.Contains(p.UserIDString)))
p.SendConsoleCommand("chat.add", new object[] { (int) chatchannel, player.Id, output.Chat });
break;
}
#else
foreach (IPlayer p in players.Connected.Where(p => !chatMessage.BlockedReceivers.Contains(p.Id)))
p.Message(output.Chat);
#endif
#if RUST
Puts($"[{chatchannel}] {output.Console}");
RCon.Broadcast(RCon.LogType.Chat, new Chat.ChatEntry
{
Channel = chatchannel,
Message = output.Console,
UserId = player.Id,
Username = player.Name,
Color = chatMessage.UsernameSettings.Color,
Time = Epoch.Current
});
#else
Puts(output.Console);
#endif
return true;
}
#endregion
#region API
private bool API_AddGroup(string group)
{
if (ChatGroup.Find(group) != null)
return false;
_chatGroups.Add(new ChatGroup(group));
SaveData(_chatGroups);
return true;
}
private List<JObject> API_GetAllGroups() => _chatGroups.ConvertAll(JObject.FromObject);
private List<JObject> API_GetUserGroups(IPlayer player) => ChatGroup.GetUserGroups(player).ConvertAll(JObject.FromObject);
private bool API_GroupExists(string group) => ChatGroup.Find(group) != null;
private ChatGroup.Field.SetValueResult? API_SetGroupField(string group, string field, string value) => ChatGroup.Find(group)?.SetField(field, value);
private Dictionary<string, object> API_GetGroupFields(string group) => ChatGroup.Find(group)?.GetFields() ?? new Dictionary<string, object>();
private Dictionary<string, object> API_GetMessageData(IPlayer player, string message) => ChatGroup.FormatMessage(player, message)?.ToDictionary();
private string API_GetFormattedUsername(IPlayer player)
{
var primary = ChatGroup.GetUserPrimaryGroup(player);
// Player has no groups - this should never happen
if (primary == null)
return player.Name;
return $"[#{primary.Username.GetUniversalColor()}][+{primary.Username.Size}]{player.Name}[/+][/#]";
}
private string API_GetFormattedMessage(IPlayer player, string message, bool console = false) => console ? ChatGroup.FormatMessage(player, message).GetOutput().Console : ChatGroup.FormatMessage(player, message).GetOutput().Chat;
private void API_RegisterThirdPartyTitle(Plugin plugin, Func<IPlayer, string> titleGetter) => _thirdPartyTitles[plugin] = titleGetter;
#endregion
#region Commands
[Command("chat"), Permission("betterchat.admin")]
private void CmdChat(IPlayer player, string cmd, string[] args)
{
cmd = player.LastCommand == CommandType.Console ? cmd : $"/{cmd}";
if (args.Length == 0)
{
player.Reply($"{cmd} group <add|remove|set|list>");
player.Reply($"{cmd} user <add|remove>");
return;
}
string argsStr = string.Join(" ", args);
var commands = new Dictionary<string, Action<string[]>>
{
["group add"] = a => {
if (a.Length != 1)
{
player.Reply($"Syntax: {cmd} group add <group>");
return;
}
string groupName = a[0].ToLower();
if (ChatGroup.Find(groupName) != null)
{
player.ReplyLang("Group Already Exists", new KeyValuePair<string, string>("group", groupName));
return;
}
ChatGroup group = new ChatGroup(groupName);
_chatGroups.Add(group);
if (!permission.GroupExists(group.GroupName))
permission.CreateGroup(group.GroupName, string.Empty, 0);
SaveData(_chatGroups);
player.ReplyLang("Group Added", new KeyValuePair<string, string>("group", groupName));
},
["group remove"] = a => {
if (a.Length != 1)
{
player.Reply($"Syntax: {cmd} group remove <group>");
return;
}
string groupName = a[0].ToLower();
ChatGroup group = ChatGroup.Find(groupName);
if (group == null)
{
player.ReplyLang("Group Does Not Exist", new KeyValuePair<string, string>("group", groupName));
return;
}
_chatGroups.Remove(group);
SaveData(_chatGroups);
player.ReplyLang("Group Removed", new KeyValuePair<string, string>("group", groupName));
},
["group set"] = a => {
if (a.Length != 3)
{
player.Reply($"Syntax: {cmd} group set <group> <field> <value>");
player.Reply($"Fields:{Environment.NewLine}{string.Join(", ", ChatGroup.Fields.Select(kvp => $"({kvp.Value.UserFriendyType}) {kvp.Key}").ToArray())}");
return;
}
string groupName = a[0].ToLower();
ChatGroup group = ChatGroup.Find(groupName);
if (group == null)
{
player.ReplyLang("Group Does Not Exist", new KeyValuePair<string, string>("group", groupName));
return;
}
string field = a[1];
string strValue = a[2];
switch (group.SetField(field, strValue))
{
case ChatGroup.Field.SetValueResult.Success:
SaveData(_chatGroups);
player.ReplyLang("Group Field Changed", new Dictionary<string, string> { ["group"] = group.GroupName, ["field"] = field, ["value"] = strValue });
break;
case ChatGroup.Field.SetValueResult.InvalidField:
player.ReplyLang("Invalid Field", new KeyValuePair<string, string>("field", field));
break;
case ChatGroup.Field.SetValueResult.InvalidValue:
player.ReplyLang("Invalid Value", new Dictionary<string, string> { ["field"] = field, ["value"] = strValue, ["type"] = ChatGroup.Fields[field].UserFriendyType });
break;
}
},
["group list"] = a =>
{
player.Reply(string.Join(", ", _chatGroups.Select(g => g.GroupName).ToArray()));
},
["group"] = a => player.Reply($"Syntax: {cmd} group <add|remove|set|list>"),
["user add"] = a => {
if (a.Length != 2)
{
player.Reply($"Syntax: {cmd} user add <username|id> <group>");
return;
}
string response;
IPlayer targetPlayer = FindPlayer(a[0], out response);
if (targetPlayer == null)
{
player.Reply(response);
return;
}
string groupName = a[1].ToLower();
ChatGroup group = ChatGroup.Find(groupName);
if (group == null)
{
player.ReplyLang("Group Does Not Exist", new KeyValuePair<string, string>("group", groupName));
return;
}
if (permission.UserHasGroup(targetPlayer.Id, groupName))
{
player.ReplyLang("Player Already In Group", new Dictionary<string, string> { ["player"] = targetPlayer.Name, ["group"] = groupName });
return;
}
group.AddUser(targetPlayer);
player.ReplyLang("Added To Group", new Dictionary<string, string> { ["player"] = targetPlayer.Name, ["group"] = groupName });
},
["user remove"] = a => {
if (a.Length != 2)
{
player.Reply($"Syntax: {cmd} user remove <username|id> <group>");
return;
}
string response;
IPlayer targetPlayer = FindPlayer(a[0], out response);
if (targetPlayer == null)
{
player.Reply(response);
return;
}
string groupName = a[1].ToLower();
ChatGroup group = ChatGroup.Find(groupName);
if (group == null)
{
player.ReplyLang("Group Does Not Exist", new KeyValuePair<string, string>("group", groupName));
return;
}
if (!permission.UserHasGroup(targetPlayer.Id, groupName))
{
player.ReplyLang("Player Not In Group", new Dictionary<string, string> { ["player"] = targetPlayer.Name, ["group"] = groupName });
return;
}
group.RemoveUser(targetPlayer);
player.ReplyLang("Removed From Group", new Dictionary<string, string> { ["player"] = targetPlayer.Name, ["group"] = groupName });
},
["user"] = a => player.Reply($"Syntax: {cmd} user <add|remove>"),
[string.Empty] = a =>
{
player.Reply($"{cmd} group <add|remove|set|list>");
player.Reply($"{cmd} user <add|remove>");
}
};
var command = commands.First(c => argsStr.ToLower().StartsWith(c.Key));
string remainingArgs = argsStr.Remove(0, command.Key.Length);
command.Value(remainingArgs.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToArray());
}
#endregion
#region Helper and Wrapper Methods
#region Player Lookup
private IPlayer FindPlayer(string nameOrID, out string response)
{
response = null;
if (IsConvertableTo<string, ulong>(nameOrID) && nameOrID.StartsWith("7656119") && nameOrID.Length == 17)
{
IPlayer result = players.All.ToList().Find((p) => p.Id == nameOrID);
if (result == null)
response = $"Could not find player with ID '{nameOrID}'";
return result;
}
List<IPlayer> foundPlayers = new List<IPlayer>();
foreach (IPlayer current in players.Connected)
{
if (current.Name.ToLower() == nameOrID.ToLower())
return current;
if (current.Name.ToLower().Contains(nameOrID.ToLower()))
foundPlayers.Add(current);
}
switch (foundPlayers.Count)
{
case 0:
response = $"Could not find player with name '{nameOrID}'";
break;
case 1:
return foundPlayers[0];
default:
string[] names = (from current in foundPlayers select current.Name).ToArray();
response = "Multiple matching players found: \n" + string.Join(", ", names);
break;
}
return null;
}
#endregion
#region Type Conversion
private bool IsConvertableTo<TSource, TResult>(TSource s)
{
TResult result;
return TryConvert(s, out result);
}
private bool TryConvert<TSource, TResult>(TSource s, out TResult c)
{
try
{
c = (TResult)Convert.ChangeType(s, typeof(TResult));
return true;
}
catch
{
c = default(TResult);
return false;
}
}
#endregion
#region Data
private void LoadData<T>(ref T data, string filename = null) => data = Core.Interface.Oxide.DataFileSystem.ReadObject<T>(filename ?? Name);
private void SaveData<T>(T data, string filename = null) => Core.Interface.Oxide.DataFileSystem.WriteObject(filename ?? Name, data);
#endregion
#region Formatting
private static string StripRichText(string text)
{
foreach (var replacement in _stringReplacements)
text = text.Replace(replacement, string.Empty);
foreach (var replacement in _regexReplacements)
text = replacement.Replace(text, string.Empty);
return Formatter.ToPlaintext(text);
}
#endregion
#region Message Wrapper
public static string GetMessage(string key, string id) => _instance.lang.GetMessage(key, _instance, id);
#endregion
#endregion
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Group Already Exists"] = "Group '{group}' already exists.",
["Group Does Not Exist"] = "Group '{group}' doesn't exist.",
["Group Field Changed"] = "Changed {field} to {value} for group '{group}'.",
["Group Added"] = "Successfully added group '{group}'.",
["Group Removed"] = "Successfully removed group '{group}'.",
["Invalid Field"] = "{field} is not a valid field. Type 'chat group set' to list all existing fields.",
["Invalid Value"] = "'{value}' is not a correct value for field '{field}'! Should be a '{type}'.",
["Player Already In Group"] = "{player} already is in group '{group}'.",
["Added To Group"] = "{player} was added to group '{group}'.",
["Player Not In Group"] = "{player} is not in group '{group}'.",
["Removed From Group"] = "{player} was removed from group '{group}'."
}, this);
}
#endregion
#region Configuration
protected override void LoadConfig()
{
base.LoadConfig();
_config = Config.ReadObject<Configuration>();
SaveConfig();
}
protected override void LoadDefaultConfig() => _config = new Configuration();
protected override void SaveConfig() => Config.WriteObject(_config);
private class Configuration
{
[JsonProperty("Maximal Titles")]
public int MaxTitles { get; set; } = 3;
[JsonProperty("Maximal Characters Per Message")]
public int MaxMessageLength { get; set; } = 128;
[JsonProperty("Reverse Title Order")]
public bool ReverseTitleOrder { get; set; } = false;
}
#endregion
#region Group Structures
public class BetterChatMessage
{
public IPlayer Player;
public string Username;
public string Message;
public List<string> Titles;
public string PrimaryGroup;
public ChatGroup.UsernameSettings UsernameSettings;
public ChatGroup.MessageSettings MessageSettings;
public ChatGroup.FormatSettings FormatSettings;
public List<string> BlockedReceivers = new List<string>();
public CancelOptions CancelOption;
public ChatGroup.FormatSettings GetOutput()
{
ChatGroup.FormatSettings output = new ChatGroup.FormatSettings();
Dictionary<string, string> replacements = new Dictionary<string, string>
{
["Title"] = string.Join(" ", Titles.ToArray()),
["Username"] = $"[#{UsernameSettings.GetUniversalColor()}][+{UsernameSettings.Size}]{Username}[/+][/#]",
["Group"] = PrimaryGroup,
["Message"] = $"[#{MessageSettings.GetUniversalColor()}][+{MessageSettings.Size}]{Message}[/+][/#]",
["ID"] = Player.Id,
["Time"] = DateTime.Now.TimeOfDay.ToString(),
["Date"] = DateTime.Now.ToString()
};
output.Chat = FormatSettings.Chat;
output.Console = FormatSettings.Console;
foreach (var replacement in replacements)
{
output.Console = StripRichText(output.Console.Replace($"{{{replacement.Key}}}", replacement.Value));
output.Chat = _instance.covalence.FormatText(output.Chat.Replace($"{{{replacement.Key}}}", replacement.Value));
}
if (output.Chat.StartsWith(" "))
output.Chat = output.Chat.Remove(0, 1);
if (output.Console.StartsWith(" "))
output.Console = output.Console.Remove(0, 1);
return output;
}
public static BetterChatMessage FromDictionary(Dictionary<string, object> dictionary)
{
var usernameSettings = dictionary[nameof(UsernameSettings)] as Dictionary<string, object>;
var messageSettings = dictionary[nameof(MessageSettings)] as Dictionary<string, object>;
var formatSettings = dictionary[nameof(FormatSettings)] as Dictionary<string, object>;
return new BetterChatMessage
{
Player = dictionary[nameof(Player)] as IPlayer,
Message = dictionary[nameof(Message)] as string,
Username = dictionary[nameof(Username)] as string,
Titles = dictionary[nameof(Titles)] as List<string>,
PrimaryGroup = dictionary[nameof(PrimaryGroup)] as string,
BlockedReceivers = dictionary[nameof(BlockedReceivers)] as List<string>,
UsernameSettings = new ChatGroup.UsernameSettings
{
Color = usernameSettings[nameof(ChatGroup.UsernameSettings.Color)] as string,
Size = (int)usernameSettings[nameof(ChatGroup.UsernameSettings.Size)]
},
MessageSettings = new ChatGroup.MessageSettings
{
Color = messageSettings[nameof(ChatGroup.MessageSettings.Color)] as string,
Size = (int)messageSettings[nameof(ChatGroup.MessageSettings.Size)]
},
FormatSettings = new ChatGroup.FormatSettings
{
Chat = formatSettings[nameof(ChatGroup.FormatSettings.Chat)] as string,
Console = formatSettings[nameof(ChatGroup.FormatSettings.Console)] as string
},
CancelOption = (CancelOptions) dictionary[nameof(CancelOption)]
};
}
public Dictionary<string, object> ToDictionary() => new Dictionary<string, object>
{
[nameof(Player)] = Player,
[nameof(Message)] = Message,
[nameof(Username)] = Username,
[nameof(Titles)] = Titles,
[nameof(PrimaryGroup)] = PrimaryGroup,
[nameof(BlockedReceivers)] = BlockedReceivers,
[nameof(UsernameSettings)] = new Dictionary<string, object>
{
[nameof(ChatGroup.UsernameSettings.Color)] = UsernameSettings.Color,
[nameof(ChatGroup.UsernameSettings.Size)] = UsernameSettings.Size
},
[nameof(MessageSettings)] = new Dictionary<string, object>
{
[nameof(ChatGroup.MessageSettings.Color)] = MessageSettings.Color,
[nameof(ChatGroup.MessageSettings.Size)] = MessageSettings.Size
},
[nameof(FormatSettings)] = new Dictionary<string, object>
{
[nameof(ChatGroup.FormatSettings.Chat)] = FormatSettings.Chat,
[nameof(ChatGroup.FormatSettings.Console)] = FormatSettings.Console
},
[nameof(CancelOption)] = CancelOption
};
public enum CancelOptions
{
None = 0,
BetterChatOnly = 1,
BetterChatAndDefault = 2
}
}
public class ChatGroup
{
private static readonly ChatGroup _fallbackGroup = new ChatGroup("default");
#if RUST
private static readonly ChatGroup _rustDeveloperGroup = new ChatGroup("rust_developer")
{
Priority = 100,
Title =
{
Text = "[Rust Developer]",
Color = "#ffaa55"
}
};
#endif
public string GroupName;
public int Priority = 0;
public TitleSettings Title = new TitleSettings();
public UsernameSettings Username = new UsernameSettings();
public MessageSettings Message = new MessageSettings();
public FormatSettings Format = new FormatSettings();
public ChatGroup(string name)
{
GroupName = name;
Title = new TitleSettings(name);
}
public static readonly Dictionary<string, Field> Fields = new Dictionary<string, Field>(StringComparer.InvariantCultureIgnoreCase)
{
["Priority"] = new Field(g => g.Priority, (g, v) => g.Priority = int.Parse(v), "number"),
["Title"] = new Field(g => g.Title.Text, (g, v) => g.Title.Text = v, "text"),
["TitleColor"] = new Field(g => g.Title.Color, (g, v) => g.Title.Color = v, "color"),
["TitleSize"] = new Field(g => g.Title.Size, (g, v) => g.Title.Size = int.Parse(v), "number"),
["TitleHidden"] = new Field(g => g.Title.Hidden, (g, v) => g.Title.Hidden = bool.Parse(v), "true/false"),
["TitleHiddenIfNotPrimary"] = new Field(g => g.Title.HiddenIfNotPrimary, (g, v) => g.Title.HiddenIfNotPrimary = bool.Parse(v), "true/false"),
["UsernameColor"] = new Field(g => g.Username.Color, (g, v) => g.Username.Color = v, "color"),
["UsernameSize"] = new Field(g => g.Username.Size, (g, v) => g.Username.Size = int.Parse(v), "number"),
["MessageColor"] = new Field(g => g.Message.Color, (g, v) => g.Message.Color = v, "color"),
["MessageSize"] = new Field(g => g.Message.Size, (g, v) => g.Message.Size = int.Parse(v), "number"),
["ChatFormat"] = new Field(g => g.Format.Chat, (g, v) => g.Format.Chat = v, "text"),
["ConsoleFormat"] = new Field(g => g.Format.Console, (g, v) => g.Format.Console = v, "text")
};
public static ChatGroup Find(string name) => _instance._chatGroups.Find(g => g.GroupName == name);
public static List<ChatGroup> GetUserGroups(IPlayer player)
{
string[] oxideGroups = _instance.permission.GetUserGroups(player.Id);
var groups = _instance._chatGroups.Where(g => oxideGroups.Any(name => g.GroupName.ToLower() == name)).ToList();
#if RUST
BasePlayer bPlayer = BasePlayer.Find(player.Id);
if (bPlayer?.IsDeveloper ?? false)
groups.Add(_rustDeveloperGroup);
#endif
return groups;
}
public static ChatGroup GetUserPrimaryGroup(IPlayer player)
{
List<ChatGroup> groups = GetUserGroups(player);
ChatGroup primary = null;
foreach (ChatGroup group in groups)
if (primary == null || group.Priority < primary.Priority)
primary = group;
return primary;
}
public static BetterChatMessage FormatMessage(IPlayer player, string message)
{
ChatGroup primary = GetUserPrimaryGroup(player);
List<ChatGroup> groups = GetUserGroups(player);
if (primary == null)
{
_instance.PrintWarning($"{player.Name} ({player.Id}) does not seem to be in any BetterChat group - falling back to plugin's default group! This should never happen! Please make sure you have a group called 'default'.");
primary = _fallbackGroup;
groups.Add(primary);
}
groups.Sort((a, b) => b.Priority.CompareTo(a.Priority));
var titles = (from g in groups
where !g.Title.Hidden && !(g.Title.HiddenIfNotPrimary && primary != g)
select $"[#{g.Title.GetUniversalColor()}][+{g.Title.Size}]{g.Title.Text}[/+][/#]")
.ToList();
titles = titles.GetRange(0, Math.Min(_instance._config.MaxTitles, titles.Count));
if (_instance._config.ReverseTitleOrder)
{
titles.Reverse();
}
foreach (var thirdPartyTitle in _instance._thirdPartyTitles)
{
try
{
string title = thirdPartyTitle.Value(player);
if (!string.IsNullOrEmpty(title))
titles.Add(title);
}
catch (Exception ex)
{
_instance.PrintError($"Error when trying to get third-party title from plugin '{thirdPartyTitle.Key}'{Environment.NewLine}{ex}");
}
}
return new BetterChatMessage
{
Player = player,
Username = StripRichText(player.Name),
Message = StripRichText(message),
Titles = titles,
PrimaryGroup = primary.GroupName,
UsernameSettings = primary.Username,
MessageSettings = primary.Message,
FormatSettings = primary.Format
};
}
public void AddUser(IPlayer player) => _instance.permission.AddUserGroup(player.Id, GroupName);
public void RemoveUser(IPlayer player) => _instance.permission.RemoveUserGroup(player.Id, GroupName);
public Field.SetValueResult SetField(string field, string value)
{
if (!Fields.ContainsKey(field))
return Field.SetValueResult.InvalidField;
try
{
Fields[field].Setter(this, value);
}
catch (FormatException)
{
return Field.SetValueResult.InvalidValue;
}
return Field.SetValueResult.Success;
}
public Dictionary<string, object> GetFields() => Fields.ToDictionary(field => field.Key, field => field.Value.Getter(this));
public override int GetHashCode() => GroupName.GetHashCode();
public class TitleSettings
{
public string Text = "[Player]";
public string Color = "#55aaff";
public int Size = 15;
public bool Hidden = false;
public bool HiddenIfNotPrimary = false;
public string GetUniversalColor() => Color.StartsWith("#") ? Color.Substring(1) : Color;
public TitleSettings(string groupName)
{
if (groupName != "default" && groupName != null)
Text = $"[{groupName}]";
}
public TitleSettings()
{
}
}
public class UsernameSettings
{
public string Color = "#55aaff";
public int Size = 15;
public string GetUniversalColor() => Color.StartsWith("#") ? Color.Substring(1) : Color;
}
public class MessageSettings
{
public string Color = "white";
public int Size = 15;
public string GetUniversalColor() => Color.StartsWith("#") ? Color.Substring(1) : Color;
}
public class FormatSettings
{
public string Chat = "{Title} {Username}: {Message}";
public string Console = "{Title} {Username}: {Message}";
}
public class Field
{
public Func<ChatGroup, object> Getter { get; }
public Action<ChatGroup, string> Setter { get; }
public string UserFriendyType { get; }
public enum SetValueResult
{
Success,
InvalidField,
InvalidValue
}
public Field(Func<ChatGroup, object> getter, Action<ChatGroup, string> setter, string userFriendyType)
{
Getter = getter;
Setter = setter;
UserFriendyType = userFriendyType;
}
}
}
#endregion
}
}
#region Extension Methods
namespace Oxide.Plugins.BetterChatExtensions
{
internal static class IPlayerExtensions
{
public static void ReplyLang(this IPlayer player, string key, Dictionary<string, string> replacements = null)
{
string message = BetterChat.GetMessage(key, player.Id);
if (replacements != null)
foreach (var replacement in replacements)
message = message.Replace($"{{{replacement.Key}}}", replacement.Value);
replacements = null;
player.Reply(message);
}
public static void ReplyLang(this IPlayer player, string key, KeyValuePair<string, string> replacement)
{
string message = BetterChat.GetMessage(key, player.Id);
message = message.Replace($"{{{replacement.Key}}}", replacement.Value);
player.Reply(message);
}
}
}
#endregion

880
plugins/BetterLoot.cs Normal file
View File

@ -0,0 +1,880 @@
using Rust;
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core.Configuration;
using Random = System.Random;
using Oxide.Core;
using Oxide.Core.Plugins;
using Facepunch.Extend;
namespace Oxide.Plugins
{
[Info("BetterLoot", "Default", "3.5.3")]
[Description("A light loot container modification system")]
public class BetterLoot : RustPlugin
{
[PluginReference]
Plugin CustomLootSpawns;
static BetterLoot bl = null;
bool Changed = true;
int populatedContainers;
StoredExportNames storedExportNames = new StoredExportNames();
StoredBlacklist storedBlacklist = new StoredBlacklist();
Random rng = new Random();
bool initialized = false;
Dictionary<string, List<string>[]> Items = new Dictionary<string, List<string>[]>();
Dictionary<string, List<string>[]> Blueprints = new Dictionary<string, List<string>[]>();
Dictionary<string, int[]> itemWeights = new Dictionary<string, int[]>();
Dictionary<string, int[]> blueprintWeights = new Dictionary<string, int[]>();
Dictionary<string, int> totalItemWeight = new Dictionary<string, int>();
Dictionary<string, int> totalBlueprintWeight = new Dictionary<string, int>();
DynamicConfigFile lootTable;
DynamicConfigFile getFile(string file) => Interface.Oxide.DataFileSystem.GetDatafile($"{this.Title}/{file}");
bool chkFile(string file) => Interface.Oxide.DataFileSystem.ExistsDatafile($"{this.Title}/{file}");
Dictionary<string, object> lootTables = null;
static List<object> lootPrefabDefaults()
{
var dp = new List<object>()
{
"assets/bundled/prefabs/radtown/crate_basic.prefab",
"assets/bundled/prefabs/radtown/crate_elite.prefab",
"assets/bundled/prefabs/radtown/crate_mine.prefab",
"assets/bundled/prefabs/radtown/crate_normal.prefab",
"assets/bundled/prefabs/radtown/crate_normal_2.prefab",
"assets/bundled/prefabs/radtown/crate_normal_2_food.prefab",
"assets/bundled/prefabs/radtown/crate_normal_2_medical.prefab",
"assets/bundled/prefabs/radtown/crate_tools.prefab",
"assets/bundled/prefabs/radtown/crate_underwater_advanced.prefab",
"assets/bundled/prefabs/radtown/crate_underwater_basic.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm ammo.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm c4.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm construction resources.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm construction tools.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm food.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm medical.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm res.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm tier1 lootbox.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm tier2 lootbox.prefab",
"assets/bundled/prefabs/radtown/dmloot/dm tier3 lootbox.prefab",
"assets/bundled/prefabs/radtown/vehicle_parts.prefab",
"assets/bundled/prefabs/radtown/foodbox.prefab",
"assets/bundled/prefabs/radtown/loot_barrel_1.prefab",
"assets/bundled/prefabs/radtown/loot_barrel_2.prefab",
"assets/bundled/prefabs/autospawn/resource/loot/loot-barrel-1.prefab",
"assets/bundled/prefabs/autospawn/resource/loot/loot-barrel-2.prefab",
"assets/bundled/prefabs/autospawn/resource/loot/trash-pile-1.prefab",
"assets/bundled/prefabs/radtown/loot_trash.prefab",
"assets/bundled/prefabs/radtown/minecart.prefab",
"assets/bundled/prefabs/radtown/oil_barrel.prefab",
"assets/prefabs/npc/m2bradley/bradley_crate.prefab",
"assets/prefabs/npc/patrol helicopter/heli_crate.prefab",
"assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab",
"assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate_oilrig.prefab",
"assets/prefabs/misc/supply drop/supply_drop.prefab",
//"assets/prefabs/npc/scientist/scientist_corpse.prefab"
};
return dp;
}
void LoadAllContainers()
{
try { lootTable = getFile("LootTables"); }
catch (JsonReaderException e)
{
PrintWarning($"JSON error in 'LootTables' > Line: {e.LineNumber} | {e.Path}");
Interface.GetMod().UnloadPlugin(this.Title);
return;
}
lootTables = new Dictionary<string, object>();
lootTables = lootTable["LootTables"] as Dictionary<string, object>;
if (lootTables == null)
lootTables = new Dictionary<string, object>();
bool wasAdded = false;
foreach (var lootPrefab in lootPrefabsToUse)
{
if (!lootTables.ContainsKey((string)lootPrefab))
{
var loot = GameManager.server.FindPrefab((string)lootPrefab)?.GetComponent<LootContainer>();
if (loot == null)
continue;
var container = new Dictionary<string, object>();
container.Add("Enabled", !((string)lootPrefab).Contains("bradley_crate") && !((string)lootPrefab).Contains("heli_crate"));
container.Add("Scrap", loot.scrapAmount);
int slots = 0;
if (loot.LootSpawnSlots.Length > 0)
{
LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
for (int i = 0; i < lootSpawnSlots.Length; i++)
slots += lootSpawnSlots[i].numberToSpawn;
}
else
slots = loot.maxDefinitionsToSpawn;
container.Add("ItemsMin", slots);
container.Add("ItemsMax", slots);
container.Add("MaxBPs", 1);
var itemList = new Dictionary<string, object>();
if (loot.lootDefinition != null)
GetLootSpawn(loot.lootDefinition, ref itemList);
else if (loot.LootSpawnSlots.Length > 0)
{
LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
foreach (var lootSpawnSlot in lootSpawnSlots)
{
GetLootSpawn(lootSpawnSlot.definition, ref itemList);
}
}
container.Add("ItemList", itemList);
lootTables.Add((string)lootPrefab, container);
wasAdded = true;
}
}
if (wasAdded)
{
lootTable.Set("LootTables", lootTables);
lootTable.Save();
}
wasAdded = false;
bool wasRemoved = false;
int activeTypes = 0;
foreach (var lootTable in lootTables.ToList())
{
var loot = GameManager.server.FindPrefab(lootTable.Key)?.GetComponent<LootContainer>();
if (loot == null)
{
lootTables.Remove(lootTable.Key);
wasRemoved = true;
continue;
}
var container = lootTable.Value as Dictionary<string, object>;
if (!container.ContainsKey("Enabled"))
{
container.Add("Enabled", true);
wasAdded = true;
}
if ((bool)container["Enabled"])
activeTypes++;
if (!container.ContainsKey("Scrap"))
{
container.Add("Scrap", loot.scrapAmount);
wasAdded = true;
}
int slots = 0;
if (loot.LootSpawnSlots.Length > 0)
{
LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
for (int i = 0; i < lootSpawnSlots.Length; i++)
slots += lootSpawnSlots[i].numberToSpawn;
}
else
slots = loot.maxDefinitionsToSpawn;
if (!container.ContainsKey("MaxBPs"))
{
container.Add("MaxBPs", 1);
wasAdded = true;
}
if (!container.ContainsKey("ItemsMin"))
{
container.Add("ItemsMin", slots);
wasAdded = true;
}
if (!container.ContainsKey("ItemsMax"))
{
container.Add("ItemsMax", slots);
wasAdded = true;
}
if (!container.ContainsKey("ItemsMax"))
{
container.Add("ItemsMax", slots);
wasAdded = true;
}
if (!container.ContainsKey("ItemList"))
{
var itemList = new Dictionary<string, object>();
if (loot.lootDefinition != null)
GetLootSpawn(loot.lootDefinition, ref itemList);
else if (loot.LootSpawnSlots.Length > 0)
{
LootContainer.LootSpawnSlot[] lootSpawnSlots = loot.LootSpawnSlots;
for (int i = 0; i < lootSpawnSlots.Length; i++)
{
LootContainer.LootSpawnSlot lootSpawnSlot = lootSpawnSlots[i];
GetLootSpawn(lootSpawnSlot.definition, ref itemList);
}
}
container.Add("ItemList", itemList);
wasAdded = true;
}
Items.Add(lootTable.Key, new List<string>[5]);
Blueprints.Add(lootTable.Key, new List<string>[5]);
for (var i = 0; i < 5; ++i)
{
Items[lootTable.Key][i] = new List<string>();
Blueprints[lootTable.Key][i] = new List<string>();
}
foreach (var itemEntry in container["ItemList"] as Dictionary<string, object>)
{
bool isBP = itemEntry.Key.EndsWith(".blueprint") ? true : false;
var def = ItemManager.FindItemDefinition(itemEntry.Key.Replace(".blueprint", ""));
if (def != null)
{
if (isBP && def.Blueprint != null && def.Blueprint.isResearchable)
{
int index = (int)def.rarity;
if (!Blueprints[lootTable.Key][index].Contains(def.shortname))
Blueprints[lootTable.Key][index].Add(def.shortname);
}
else
{
int index = 0;
object indexoverride;
if (rarityItemOverride.TryGetValue(def.shortname, out indexoverride))
index = Convert.ToInt32(indexoverride);
else
index = (int)def.rarity;
if (!Items[lootTable.Key][index].Contains(def.shortname))
Items[lootTable.Key][index].Add(def.shortname);
}
}
}
totalItemWeight.Add(lootTable.Key, 0);
totalBlueprintWeight.Add(lootTable.Key, 0);
itemWeights.Add(lootTable.Key, new int[5]);
blueprintWeights.Add(lootTable.Key, new int[5]);
for (var i = 0; i < 5; ++i)
{
totalItemWeight[lootTable.Key] += (itemWeights[lootTable.Key][i] = ItemWeight(baseItemRarity, i) * Items[lootTable.Key][i].Count);
totalBlueprintWeight[lootTable.Key] += (blueprintWeights[lootTable.Key][i] = ItemWeight(baseItemRarity, i) * Blueprints[lootTable.Key][i].Count);
}
}
if (wasAdded || wasRemoved)
{
lootTable.Set("LootTables", lootTables);
lootTable.Save();
}
lootTable.Clear();
Puts($"Using '{activeTypes}' active of '{lootTables.Count}' supported containertypes");
}
int ItemWeight(double baseRarity, int index) { return (int)(Math.Pow(baseRarity, 4 - index) * 1000); }
void GetLootSpawn(LootSpawn lootSpawn, ref Dictionary<string, object> items)
{
if (lootSpawn.subSpawn != null && lootSpawn.subSpawn.Length > 0)
{
foreach (var entry in lootSpawn.subSpawn)
GetLootSpawn(entry.category, ref items);
return;
}
if (lootSpawn.items != null && lootSpawn.items.Length > 0)
{
foreach (var amount in lootSpawn.items)
{
object options = GetAmounts(amount, 1);
string itemName = amount.itemDef.shortname;
if (amount.itemDef.spawnAsBlueprint)
itemName += ".blueprint";
if (!items.ContainsKey(itemName))
items.Add(itemName, options);
}
}
}
object GetAmounts(ItemAmount amount, int mul = 1)
{
if (amount.itemDef.isWearable || (amount.itemDef.condition.enabled && amount.itemDef.GetComponent<ItemModDeployable>() == null))
mul = 1;
object options = new Dictionary<string, object>
{
["Min"] = (int)amount.amount * mul,
["Max"] = ((ItemAmountRanged)amount).maxAmount > 0f &&
((ItemAmountRanged)amount).maxAmount > amount.amount
? (int)((ItemAmountRanged)amount).maxAmount * mul
: (int)amount.amount * mul,
};
return options;
}
static Dictionary<string, object> defaultItemOverride()
{
var dp = new Dictionary<string, object>();
dp.Add("autoturret", 4);
dp.Add("lmg.m249", 4);
dp.Add("targeting.computer", 3);
return dp;
}
double baseItemRarity;
double blueprintProbability;
bool removeStackedContainers;
bool listUpdatesOnLoaded;
double hammerLootCycleTime;
int lootMultiplier;
int scrapMultiplier;
bool enableHammerLootCycle;
Dictionary<string, object> rarityItemOverride = null;
List<object> lootPrefabsToUse = null;
object GetConfig(string menu, string datavalue, object defaultValue)
{
var data = Config[menu] as Dictionary<string, object>;
if (data == null)
{
data = new Dictionary<string, object>();
Config[menu] = data;
Changed = true;
}
object value;
if (data.TryGetValue(datavalue, out value)) return value;
value = defaultValue;
data[datavalue] = value;
Changed = true;
return value;
}
void LoadVariables()
{
baseItemRarity = 2;
rarityItemOverride = (Dictionary<string, object>)GetConfig("Rarity", "Override", defaultItemOverride());
lootPrefabsToUse = (List<object>)GetConfig("Generic", "WatchedPrefabs", lootPrefabDefaults());
listUpdatesOnLoaded = Convert.ToBoolean(GetConfig("Generic", "listUpdatesOnLoaded", true));
removeStackedContainers = Convert.ToBoolean(GetConfig("Generic", "removeStackedContainers", true));
blueprintProbability = Convert.ToDouble(GetConfig("Generic", "blueprintProbability", 0.11));
hammerLootCycleTime = Convert.ToDouble(GetConfig("Loot", "hammerLootCycleTime", 3));
lootMultiplier = Convert.ToInt32(GetConfig("Loot", "lootMultiplier", 1));
scrapMultiplier = Convert.ToInt32(GetConfig("Loot", "scrapMultiplier", 1));
enableHammerLootCycle = Convert.ToBoolean(GetConfig("Loot", "enableHammerLootCycle", false));
if (!Changed) return;
SaveConfig();
Changed = false;
}
class StoredBlacklist
{
public List<string> ItemList = new List<string>();
public StoredBlacklist()
{
}
}
void LoadBlacklist()
{
storedBlacklist = Interface.GetMod().DataFileSystem.ReadObject<StoredBlacklist>("BetterLoot\\Blacklist");
if (storedBlacklist.ItemList.Count == 0)
{
Puts("No Blacklist found, creating new file...");
storedBlacklist = new StoredBlacklist();
storedBlacklist.ItemList.Add("flare");
Interface.GetMod().DataFileSystem.WriteObject("BetterLoot\\Blacklist", storedBlacklist);
return;
}
}
void SaveBlacklist() => Interface.GetMod().DataFileSystem.WriteObject("BetterLoot\\Blacklist", storedBlacklist);
protected override void LoadDefaultConfig()
{
Config.Clear();
LoadVariables();
}
void Init()
{
LoadVariables();
LoadBlacklist();
bl = this;
}
void OnServerInitialized()
{
ItemManager.Initialize();
LoadAllContainers();
UpdateInternals(listUpdatesOnLoaded);
}
//void OnLootEntity(BasePlayer player, BaseEntity target)
//{
//Puts($"{player.displayName} looted {target.PrefabName}");
//}
void Unload()
{
var gameObjects = UnityEngine.Object.FindObjectsOfType<HammerHitLootCycle>().ToList();
if (gameObjects.Count > 0)
{
foreach (var objects in gameObjects)
{
UnityEngine.Object.Destroy(objects);
}
}
}
void UpdateInternals(bool doLog)
{
SaveExportNames();
if (Changed)
{
SaveConfig();
Changed = false;
}
Puts("Updating internals ...");
populatedContainers = 0;
NextTick(() =>
{
if (removeStackedContainers)
FixLoot();
foreach (var container in BaseNetworkable.serverEntities.Where(p => p != null && p.GetComponent<BaseEntity>() != null && p is LootContainer).Cast<LootContainer>().ToList())
{
if (container == null)
continue;
if (CustomLootSpawns != null && (CustomLootSpawns && (bool)CustomLootSpawns?.Call("IsLootBox", container.GetComponent<BaseEntity>())))
continue;
if (PopulateContainer(container))
populatedContainers++;
}
Puts($"Populated '{populatedContainers}' supported containers.");
initialized = true;
populatedContainers = 0;
ItemManager.DoRemoves();
});
}
void FixLoot()
{
var spawns = Resources.FindObjectsOfTypeAll<LootContainer>()
.Where(c => c.isActiveAndEnabled).
OrderBy(c => c.transform.position.x).ThenBy(c => c.transform.position.z).ThenBy(c => c.transform.position.z)
.ToList();
var count = spawns.Count();
var racelimit = count * count;
var antirace = 0;
var deleted = 0;
for (var i = 0; i < count; i++)
{
var box = spawns[i];
var pos = new Vector2(box.transform.position.x, box.transform.position.z);
if (++antirace > racelimit)
{
return;
}
var next = i + 1;
while (next < count)
{
var box2 = spawns[next];
var pos2 = new Vector2(box2.transform.position.x, box2.transform.position.z);
var distance = Vector2.Distance(pos, pos2);
if (++antirace > racelimit)
{
return;
}
if (distance < 0.25f)
{
spawns.RemoveAt(next);
count--;
(box2 as BaseEntity).KillMessage();
deleted++;
}
else break;
}
}
if (deleted > 0)
Puts($"Removed {deleted} stacked LootContainer");
else
Puts($"No stacked LootContainer found.");
ItemManager.DoRemoves();
}
bool PopulateContainer(LootContainer container)
{
Dictionary<string, object> con;
object containerobj;
if (!lootTables.TryGetValue(container.PrefabName, out containerobj))
return false;
con = containerobj as Dictionary<string, object>;
if (!(bool)con["Enabled"])
return false;
var lootitemcount = (con["ItemList"] as Dictionary<string, object>)?.Count();
int itemCount = Mathf.RoundToInt(UnityEngine.Random.Range(Convert.ToSingle(Mathf.Min((int)con["ItemsMin"], (int)con["ItemsMax"])) * 100f, Convert.ToSingle(Mathf.Max((int)con["ItemsMin"], (int)con["ItemsMax"])) * 100f) / 100f);
if (lootitemcount > 0 && itemCount > lootitemcount && lootitemcount < 36)
itemCount = (int)lootitemcount;
if (container.inventory == null)
{
container.inventory = new ItemContainer();
container.inventory.ServerInitialize(null, 36);
container.inventory.GiveUID();
}
else
{
while (container.inventory.itemList.Count > 0)
{
var item = container.inventory.itemList[0];
item.RemoveFromContainer();
item.Remove(0f);
}
container.inventory.capacity = 36;
}
var items = new List<Item>();
var itemNames = new List<string>();
var itemBlueprints = new List<int>();
var maxRetry = 10;
for (int i = 0; i < itemCount; ++i)
{
if (maxRetry == 0)
{
break;
}
var item = MightyRNG(container.PrefabName, itemCount, (bool)(itemBlueprints.Count >= (int)con["MaxBPs"]));
if (item == null)
{
--maxRetry;
--i;
continue;
}
if (itemNames.Contains(item.info.shortname) || (item.IsBlueprint() && itemBlueprints.Contains(item.blueprintTarget)))
{
item.Remove(0f);
--maxRetry;
--i;
continue;
}
else
if (item.IsBlueprint())
itemBlueprints.Add(item.blueprintTarget);
else
itemNames.Add(item.info.shortname);
items.Add(item);
if (storedBlacklist.ItemList.Contains(item.info.shortname))
{
items.Remove(item);
}
}
foreach (var item in items.Where(x => x != null && x.IsValid()))
item.MoveToContainer(container.inventory, -1, false);
if ((int)con["Scrap"] > 0)
{
int scrapCount = (int)con["Scrap"];
Item item = ItemManager.Create(ItemManager.FindItemDefinition("scrap"), scrapCount * scrapMultiplier, 0uL);
item.MoveToContainer(container.inventory, -1, false);
}
container.inventory.capacity = container.inventory.itemList.Count;
container.inventory.MarkDirty();
container.SendNetworkUpdate();
populatedContainers++;
return true;
}
Item MightyRNG(string type, int itemCount, bool blockBPs = false)
{
bool asBP = rng.NextDouble() < blueprintProbability && !blockBPs;
List<string> selectFrom;
int limit = 0;
string itemName;
Item item;
int maxRetry = 10 * itemCount;
do
{
selectFrom = null;
item = null;
if (asBP)
{
var r = rng.Next(totalBlueprintWeight[type]);
for (var i = 0; i < 5; ++i)
{
limit += blueprintWeights[type][i];
if (r < limit)
{
selectFrom = Blueprints[type][i];
break;
}
}
}
else
{
var r = rng.Next(totalItemWeight[type]);
for (var i = 0; i < 5; ++i)
{
limit += itemWeights[type][i];
if (r < limit)
{
selectFrom = Items[type][i];
break;
}
}
}
if (selectFrom == null)
{
if (--maxRetry <= 0)
break;
continue;
}
itemName = selectFrom[rng.Next(0, selectFrom.Count)];
ItemDefinition itemDef = ItemManager.FindItemDefinition(itemName);
if (asBP && itemDef.Blueprint != null && itemDef.Blueprint.isResearchable)
{
var blueprintBaseDef = ItemManager.FindItemDefinition("blueprintbase");
item = ItemManager.Create(blueprintBaseDef, 1, 0uL);
item.blueprintTarget = itemDef.itemid;
}
else
item = ItemManager.CreateByName(itemName, 1);
if (item == null || item.info == null)
continue;
break;
} while (true);
if (item == null)
return null;
object itemOptions;
if (((lootTables[type] as Dictionary<string, object>)["ItemList"] as Dictionary<string, object>).TryGetValue(item.info.shortname, out itemOptions))
{
Dictionary<string, object> options = itemOptions as Dictionary<string, object>;
item.amount = UnityEngine.Random.Range(Math.Min((int)options["Min"], (int)options["Max"]), Math.Max((int)options["Min"], (int)options["Max"])) * lootMultiplier;
//if (options.ContainsKey("SkinId"))
//item.skin = (uint)options["SkinId"];
}
item.OnVirginSpawn();
return item;
}
object OnLootSpawn(LootContainer container)
{
if (!initialized || container == null)
return null;
if (CustomLootSpawns != null && (CustomLootSpawns && (bool)CustomLootSpawns?.Call("IsLootBox", container.GetComponent<BaseEntity>())))
return null;
if (PopulateContainer(container))
{
ItemManager.DoRemoves();
return true;
}
return null;
}
static int RarityIndex(Rarity rarity)
{
switch (rarity)
{
case Rarity.None: return 0;
case Rarity.Common: return 1;
case Rarity.Uncommon: return 2;
case Rarity.Rare: return 3;
case Rarity.VeryRare: return 4;
}
return -1;
}
bool ItemExists(string name)
{
foreach (var def in ItemManager.itemList)
{
if (def.shortname != name)
continue;
var testItem = ItemManager.CreateByName(name, 1);
if (testItem != null)
{
testItem.Remove(0f);
return true;
}
}
return false;
}
bool isSupplyDropActive()
{
Dictionary<string, object> con;
object containerobj;
if (!lootTables.TryGetValue("assets/prefabs/misc/supply drop/supply_drop.prefab", out containerobj))
return false;
con = containerobj as Dictionary<string, object>;
if ((bool)con["Enabled"])
return true;
return false;
}
class StoredExportNames
{
public int version;
public Dictionary<string, string> AllItemsAvailable = new Dictionary<string, string>();
public StoredExportNames()
{
}
}
void SaveExportNames()
{
storedExportNames = Interface.GetMod().DataFileSystem.ReadObject<StoredExportNames>("BetterLoot\\NamesList");
if (storedExportNames.AllItemsAvailable.Count == 0 || (int)storedExportNames.version != Rust.Protocol.network)
{
storedExportNames = new StoredExportNames();
var exportItems = new List<ItemDefinition>(ItemManager.itemList);
storedExportNames.version = Rust.Protocol.network;
foreach (var it in exportItems)
storedExportNames.AllItemsAvailable.Add(it.shortname, it.displayName.english);
Interface.GetMod().DataFileSystem.WriteObject("BetterLoot\\NamesList", storedExportNames);
Puts($"Exported {storedExportNames.AllItemsAvailable.Count} items to 'NamesList'");
}
}
[ChatCommand("blacklist")]
void cmdChatBlacklist(BasePlayer player, string command, string[] args)
{
string usage = "Usage: /blacklist [additem|deleteitem] \"ITEMNAME\"";
if (!initialized)
{
SendReply(player, string.Format("Plugin not enabled."));
return;
}
if (args.Length == 0)
{
if (storedBlacklist.ItemList.Count == 0)
{
SendReply(player, string.Format("There are no blacklisted items"));
}
else
{
var sb = new StringBuilder();
foreach (var item in storedBlacklist.ItemList)
{
if (sb.Length > 0)
sb.Append(", ");
sb.Append(item);
}
SendReply(player, string.Format("Blacklisted items: {0}", sb.ToString()));
}
return;
}
if (!ServerUsers.Is(player.userID, ServerUsers.UserGroup.Owner))
{
//SendReply(player, string.Format(lang.GetMessage("msgNotAuthorized", this, player.UserIDString)));
SendReply(player, "You are not authorized to use this command");
return;
}
if (args.Length != 2)
{
SendReply(player, usage);
return;
}
if (args[0] == "additem")
{
if (!ItemExists(args[1]))
{
SendReply(player, string.Format("Not a valid item: {0}", args[1]));
return;
}
if (!storedBlacklist.ItemList.Contains(args[1]))
{
storedBlacklist.ItemList.Add(args[1]);
UpdateInternals(false);
SendReply(player, string.Format("The item '{0}' is now blacklisted", args[1]));
SaveBlacklist();
return;
}
else
{
SendReply(player, string.Format("The item '{0}' is already blacklisted", args[1]));
return;
}
}
else if (args[0] == "deleteitem")
{
if (!ItemExists(args[1]))
{
SendReply(player, string.Format("Not a valid item: {0}", args[1]));
return;
}
if (storedBlacklist.ItemList.Contains(args[1]))
{
storedBlacklist.ItemList.Remove(args[1]);
UpdateInternals(false);
SendReply(player, string.Format("The item '{0}' is now no longer blacklisted", args[1]));
SaveBlacklist();
return;
}
else
{
SendReply(player, string.Format("The item '{0}' is not blacklisted", args[1]));
return;
}
}
else
{
SendReply(player, usage);
return;
}
}
#region Hammer loot cycle
object OnMeleeAttack(BasePlayer player, HitInfo c)
{
//Puts($"OnMeleeAttack works! You hit {c.HitEntity.PrefabName}"); DEBUG FOR TESTING
var item = player.GetActiveItem();
if (item.hasCondition) return null;
//Puts($"{item.ToString()}");
if (!player.IsAdmin || c.HitEntity.GetComponent<LootContainer>() == null || !item.ToString().Contains("hammer") || !enableHammerLootCycle) return null;
var inv = c.HitEntity.GetComponent<StorageContainer>();
inv.gameObject.AddComponent<HammerHitLootCycle>();
player.inventory.loot.StartLootingEntity(inv, false);
player.inventory.loot.AddContainer(inv.inventory);
player.inventory.loot.SendImmediate();
player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", inv.panelName);
//Timer s = timer.Every(1f, () => { PopulateContainer(inv})
return null;
}
class HammerHitLootCycle : FacepunchBehaviour
{
void Awake()
{
if (!bl.initialized) return;
InvokeRepeating(Repeater, (float)bl.hammerLootCycleTime, (float)bl.hammerLootCycleTime);
}
void Repeater()
{
if (!enabled) return;
LootContainer loot = GetComponent<LootContainer>();
bl.Puts($"{loot}");
bl.PopulateContainer(loot);
}
private void PlayerStoppedLooting(BasePlayer player)
{
//bl.Puts($"Ended looting of the box"); Doesn't call but it works for a reason I don't quite understand
CancelInvoke(Repeater);
Destroy(this);
}
}
#endregion
}
}

705
plugins/BlueprintShare.cs Normal file
View File

@ -0,0 +1,705 @@
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Blueprint Share", "c_creep", "1.2.4")]
[Description("Allows players to share researched blueprints with their friends, clan or team")]
class BlueprintShare : RustPlugin
{
#region Fields
[PluginReference] private Plugin Clans, ClansReborn, Friends;
private StoredData storedData;
private bool clansEnabled = true, friendsEnabled = true, teamsEnabled = true, recycleEnabled = false;
#endregion
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Prefix"] = "<color=#D85540>[Blueprint Share] </color>",
["ArgumentsError"] = "Error, incorrect arguments. Try /bs help.",
["Help"] = "<color=#D85540>Blueprint Share Help:</color>\n\n<color=#D85540>/bs toggle</color> - Toggles the sharing of blueprints.\n<color=#D85540>/bs share <player></color> - Shares your blueprints with other player.",
["ToggleOn"] = "You have enabled sharing blueprints.",
["ToggleOff"] = "You have disabled sharing blueprints.",
["NoPermission"] = "You don't have permission to use this command!",
["CannotShare"] = "You cannot share blueprints with this player because they aren't a friend or in the same clan or team!",
["NoTarget"] = "You didn't specifiy a player to share with!",
["TargetEqualsPlayer"] = "You cannot share blueprints with your self!",
["PlayerNotFound"] = "Couldn't find a player with that name!",
["MultiplePlayersFound"] = "Found multiple players with a similar name: {0}",
["ShareSuccess"] = "You shared {0} blueprints with {1}.",
["ShareFailure"] = "You don't have any new blueprints to share with {0}",
["ShareReceieve"] = "{0} has shared {1} blueprints with you.",
["Recycle"] = "You have kept the blueprint because no one learnt the blueprint.",
["ShareError"] = "An error occured while attempting to share items with another player"
}, this);
}
private string GetLangValue(string key, string id = null, params object[] args)
{
var msg = lang.GetMessage(key, this, id);
return args.Length > 0 ? string.Format(msg, args) : msg;
}
#endregion
#region Oxide Hooks
private void Init()
{
LoadData();
LoadDefaultConfig();
permission.RegisterPermission("blueprintshare.toggle", this);
permission.RegisterPermission("blueprintshare.share", this);
}
private void OnPlayerConnected(BasePlayer player)
{
var playerUID = player.UserIDString;
if (!PlayerDataExists(playerUID))
{
CreateNewPlayerData(playerUID);
}
}
private void OnItemAction(Item item, string action, BasePlayer player)
{
if (player != null)
{
if (action == "study")
{
var itemShortName = item.blueprintTargetDef.shortname;
if (CanShareBlueprint(itemShortName, player))
{
item.Remove();
}
}
}
}
private void OnTechTreeNodeUnlocked(Workbench workbench, TechTreeData.NodeInstance node, BasePlayer player)
{
if (workbench != null)
{
if (node != null)
{
if (player != null)
{
var itemShortName = node.itemDef.shortname;
CanShareBlueprint(itemShortName, player);
}
}
}
}
#endregion
#region General Methods
private bool CanShareBlueprint(string itemShortName, BasePlayer player)
{
if (player == null) return false;
if (string.IsNullOrEmpty(itemShortName)) return false;
var playerUID = player.UserIDString;
if (SharingEnabled(playerUID))
{
if (InTeam(player.userID) || InClan(player.userID) || HasFriends(player.userID))
{
if (SomeoneWillLearnBlueprint(player, itemShortName))
{
TryInsertBlueprint(player, itemShortName);
ShareWithPlayers(player, itemShortName);
HandleAdditionalBlueprints(player, itemShortName);
return true;
}
else
{
if (recycleEnabled)
{
player.ChatMessage(GetLangValue("Recycle", playerUID));
return true;
}
return false;
}
}
else
{
return false;
}
}
else
{
TryInsertBlueprint(player, itemShortName);
return true;
}
}
private void HandleAdditionalBlueprints(BasePlayer player, string itemShortName)
{
var additionalBlueprints = GetItemDefinition(itemShortName).Blueprint.additionalUnlocks;
if (additionalBlueprints.Count > 0)
{
foreach (var blueprint in additionalBlueprints)
{
var additionalItemShortName = blueprint.shortname;
if (!string.IsNullOrEmpty(additionalItemShortName))
{
if (SomeoneWillLearnBlueprint(player, additionalItemShortName))
{
ShareWithPlayers(player, additionalItemShortName);
}
}
}
}
}
private void ShareWithPlayers(BasePlayer sharer, string itemShortName)
{
if (sharer == null || string.IsNullOrEmpty(itemShortName)) return;
var recipients = SelectSharePlayers(sharer);
foreach (var recipient in recipients)
{
if (recipient != null)
{
if (UnlockBlueprint(recipient, itemShortName))
{
TryInsertBlueprint(recipient, itemShortName);
}
}
}
}
private void ShareWithPlayer(BasePlayer sharer, BasePlayer recipient)
{
var sharerUID = sharer.UserIDString;
var recipientUID = recipient.UserIDString;
if (SameTeam(sharer, recipient) || SameClan(sharerUID, recipientUID) || AreFriends(sharerUID, recipientUID))
{
var itemShortNames = LoadBlueprints(sharerUID);
if (itemShortNames != null)
{
if (itemShortNames.Count > 0)
{
var learnedBlueprints = 0;
foreach (var itemShortName in itemShortNames)
{
if (recipient == null || string.IsNullOrEmpty(itemShortName)) return;
if (UnlockBlueprint(recipient, itemShortName))
{
TryInsertBlueprint(recipient, itemShortName);
learnedBlueprints++;
}
}
if (learnedBlueprints > 0)
{
sharer.ChatMessage(GetLangValue("Prefix", sharerUID) + GetLangValue("ShareSuccess", sharerUID, learnedBlueprints, recipient.displayName));
recipient.ChatMessage(GetLangValue("Prefix", recipientUID) + GetLangValue("ShareReceieve", recipientUID, sharer.displayName, learnedBlueprints));
}
else
{
sharer.ChatMessage(GetLangValue("Prefix", sharerUID) + GetLangValue("ShareFailure", sharerUID, recipient.displayName));
}
}
else
{
sharer.ChatMessage(GetLangValue("Prefix", sharerUID) + GetLangValue("ShareFailure", sharerUID, recipient.displayName));
}
}
else
{
sharer.ChatMessage(GetLangValue("ShareError", sharerUID));
}
}
}
private bool UnlockBlueprint(BasePlayer player, string itemShortName)
{
if (player == null) return false;
if (string.IsNullOrEmpty(itemShortName)) return false;
var blueprintComponent = player.blueprints;
if (blueprintComponent == null) return false;
var itemDefinition = GetItemDefinition(itemShortName);
if (itemDefinition == null) return false;
if (blueprintComponent.HasUnlocked(itemDefinition)) return false;
var soundEffect = new Effect("assets/prefabs/deployable/research table/effects/research-success.prefab", player.transform.position, Vector3.zero);
if (soundEffect == null) return false;
EffectNetwork.Send(soundEffect, player.net.connection);
blueprintComponent.Unlock(itemDefinition);
return true;
}
private bool SomeoneWillLearnBlueprint(BasePlayer sharer, string itemShortName)
{
if (sharer == null || string.IsNullOrEmpty(itemShortName)) return false;
var players = SelectSharePlayers(sharer);
if (players.Count > 0)
{
var blueprintItem = GetItemDefinition(itemShortName);
if (blueprintItem != null)
{
var counter = 0;
foreach (var player in players)
{
if (player != null)
{
if (!player.blueprints.HasUnlocked(blueprintItem))
{
counter++;
}
}
}
return counter > 0;
}
else
{
return false;
}
}
else
{
return false;
}
}
private List<BasePlayer> SelectSharePlayers(BasePlayer player)
{
var playersToShareWith = new List<BasePlayer>();
var playerUID = player.userID;
if (clansEnabled && (Clans != null || ClansReborn != null) && InClan(playerUID))
{
playersToShareWith.AddRange(GetClanMembers(playerUID));
}
if (friendsEnabled && Friends != null && HasFriends(playerUID))
{
playersToShareWith.AddRange(GetFriends(playerUID));
}
if (teamsEnabled && InTeam(playerUID))
{
playersToShareWith.AddRange(GetTeamMembers(playerUID));
}
return playersToShareWith;
}
private List<string> LoadBlueprints(string playerUID)
{
if (PlayerDataExists(playerUID))
{
return storedData.players[playerUID].learntBlueprints;
}
else
{
CreateNewPlayerData(playerUID);
if (storedData.players[playerUID].learntBlueprints == null)
{
return storedData.players[playerUID].learntBlueprints = new List<string>();
}
else
{
return storedData.players[playerUID].learntBlueprints;
}
}
}
private void TryInsertBlueprint(BasePlayer player, string itemShortName)
{
var playerUID = player.UserIDString;
if (PlayerDataExists(playerUID))
{
InsertBlueprint(playerUID, itemShortName);
}
else
{
CreateNewPlayerData(playerUID);
InsertBlueprint(playerUID, itemShortName);
}
}
private void InsertBlueprint(string playerUID, string itemShortName)
{
if (string.IsNullOrEmpty(playerUID) || string.IsNullOrEmpty(itemShortName)) return;
if (!storedData.players[playerUID].learntBlueprints.Contains(itemShortName))
{
storedData.players[playerUID].learntBlueprints.Add(itemShortName);
SaveData();
}
}
#endregion
#region Config
protected override void LoadDefaultConfig()
{
Config["ClansEnabled"] = clansEnabled = GetConfigValue("ClansEnabled", true);
Config["FriendsEnabled"] = friendsEnabled = GetConfigValue("FriendsEnabled", true);
Config["TeamsEnabled"] = teamsEnabled = GetConfigValue("TeamsEnabled", true);
Config["RecycleBlueprints"] = recycleEnabled = GetConfigValue("RecycleBlueprints", false);
SaveConfig();
}
private T GetConfigValue<T>(string name, T defaultValue)
{
return Config[name] == null ? defaultValue : (T)Convert.ChangeType(Config[name], typeof(T));
}
#endregion
#region Friends Methods
private bool HasFriends(ulong playerUID)
{
if (Friends == null) return false;
var friendsList = Friends.Call<ulong[]>("GetFriends", playerUID);
return friendsList != null && friendsList.Length != 0;
}
private List<BasePlayer> GetFriends(ulong playerUID)
{
var friendsList = new List<BasePlayer>();
var friends = Friends.Call<ulong[]>("GetFriends", playerUID);
foreach (var friendUID in friends)
{
var friend = RustCore.FindPlayerById(friendUID);
friendsList.Add(friend);
}
return friendsList;
}
private bool AreFriends(string sharerUID, string playerUID) => Friends == null ? false : Friends.Call<bool>("AreFriends", sharerUID, playerUID);
#endregion
#region Clan Methods
private bool InClan(ulong playerUID)
{
if (ClansReborn == null && Clans == null) return false;
var clanName = Clans?.Call<string>("GetClanOf", playerUID);
return clanName != null;
}
private List<BasePlayer> GetClanMembers(ulong playerUID)
{
var membersList = new List<BasePlayer>();
var clanName = Clans?.Call<string>("GetClanOf", playerUID);
if (!string.IsNullOrEmpty(clanName))
{
var clan = Clans?.Call<JObject>("GetClan", clanName);
if (clan != null && clan is JObject)
{
var members = clan.GetValue("members");
if (members != null)
{
foreach (var member in members)
{
ulong clanMemberUID;
if (!ulong.TryParse(member.ToString(), out clanMemberUID)) continue;
BasePlayer clanMember = RustCore.FindPlayerById(clanMemberUID);
membersList.Add(clanMember);
}
}
}
}
return membersList;
}
private bool SameClan(string sharerUID, string playerUID) => ClansReborn == null && Clans == null ? false : (bool)Clans?.Call<bool>("IsClanMember", sharerUID, playerUID);
#endregion
#region Team Methods
private bool InTeam(ulong playerUID)
{
var player = RustCore.FindPlayerById(playerUID);
return player.currentTeam != 0;
}
private List<BasePlayer> GetTeamMembers(ulong playerUID)
{
var membersList = new List<BasePlayer>();
var player = RustCore.FindPlayerById(playerUID);
var teamMembers = player.Team.members;
foreach (var teamMemberUID in teamMembers)
{
var teamMember = RustCore.FindPlayerById(teamMemberUID);
if (teamMember != null)
{
membersList.Add(teamMember);
}
}
return membersList;
}
private bool SameTeam(BasePlayer sharer, BasePlayer player) => sharer.currentTeam == player.currentTeam;
#endregion
#region Utility Methods
private BasePlayer FindPlayer(string playerName, BasePlayer player, string playerUID)
{
var targets = FindPlayers(playerName);
if (targets.Count <= 0)
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("PlayerNotFound", playerUID));
return null;
}
if (targets.Count > 1)
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("MultiplePlayersFound", playerUID));
return null;
}
return targets.First();
}
private List<BasePlayer> FindPlayers(string playerName)
{
if (string.IsNullOrEmpty(playerName)) return null;
return BasePlayer.allPlayerList.Where(p => p && p.UserIDString == playerName || p.displayName.Contains(playerName, CompareOptions.OrdinalIgnoreCase)).ToList();
}
private ItemDefinition GetItemDefinition(string itemShortName)
{
if (string.IsNullOrEmpty(itemShortName)) return null;
var itemDefinition = ItemManager.FindItemDefinition(itemShortName.ToLower());
return itemDefinition;
}
#endregion
#region Data
private class StoredData
{
public Dictionary<string, PlayerData> players = new Dictionary<string, PlayerData>();
}
private class PlayerData
{
public bool sharingEnabled;
public List<string> learntBlueprints;
}
private void CreateData()
{
storedData = new StoredData();
SaveData();
}
private void LoadData()
{
if (Interface.Oxide.DataFileSystem.ExistsDatafile(Name))
{
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
}
else
{
CreateData();
}
}
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);
private bool PlayerDataExists(string playerUID) => storedData.players.ContainsKey(playerUID);
private void CreateNewPlayerData(string playerUID)
{
storedData.players.Add(playerUID, new PlayerData
{
sharingEnabled = true,
learntBlueprints = new List<string>()
});
SaveData();
}
#endregion
#region Chat Commands
[ChatCommand("bs")]
private void ToggleCommand(BasePlayer player, string command, string[] args)
{
var playerUID = player.UserIDString;
if (args.Length < 1)
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("Help", playerUID));
return;
}
switch (args[0].ToLower())
{
case "help":
{
player.ChatMessage(GetLangValue("Help", playerUID));
break;
}
case "toggle":
{
if (permission.UserHasPermission(playerUID, "blueprintshare.toggle"))
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue(SharingEnabled(playerUID) ? "ToggleOff" : "ToggleOn", playerUID));
if (storedData.players.ContainsKey(playerUID))
{
storedData.players[playerUID].sharingEnabled = !storedData.players[playerUID].sharingEnabled;
SaveData();
}
}
else
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("NoPermission", playerUID));
}
break;
}
case "share":
{
if (permission.UserHasPermission(playerUID, "blueprintshare.share"))
{
if (args.Length == 2)
{
var target = FindPlayer(args[1], player, playerUID);
if (target == null) return;
if (target == player)
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("TargetEqualsPlayer", playerUID));
return;
}
ShareWithPlayer(player, target);
}
else
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("NoTarget", playerUID));
return;
}
}
else
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("NoPermission", playerUID));
}
break;
}
default:
{
player.ChatMessage(GetLangValue("Prefix", playerUID) + GetLangValue("ArgumentsError", playerUID));
break;
}
}
}
#endregion
#region API
private bool SharingEnabled(string playerUID) => storedData.players.ContainsKey(playerUID) ? storedData.players[playerUID].sharingEnabled : true;
#endregion
}
}

1318
plugins/Clans.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,693 @@
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using System.Collections.Generic;
using System.Linq;
namespace Oxide.Plugins
{
[Info("Crafting Controller", "Whispers88", "3.2.2")]
[Description("Allows you to modify the time spend crafting and which items can be crafted")]
//Credits to previous authors Nivex & Mughisi
public class CraftingController : RustPlugin
{
#region Config
private Configuration config;
private static Dictionary<string, float> defaultsetup = new Dictionary<string, float>();
public class CraftingData
{
public bool canCraft;
public bool canResearch;
public bool useCrafteRateMultiplier;
public float craftTime;
public int workbenchLevel;
public ulong defaultskinid;
public CraftingData()
{
canCraft = true;
canResearch = true;
useCrafteRateMultiplier = true;
craftTime = 0;
workbenchLevel = -1;
defaultskinid = 0;
}
}
public class Configuration
{
[JsonProperty("Default crafting rate percentage")]
public float CraftingRate = 50;
[JsonProperty("Save commands to config (save config changes via command to the configuration)")]
public bool SaveCommands = true;
[JsonProperty("Simple Mode (disables: instant bulk craft, skin options and full inventory checks for better performance)")]
public bool SimpleMode = false;
[JsonProperty("Allow crafting when inventory is full")]
public bool FullInventory = false;
[JsonProperty("Complete crafting on server shut down")]
public bool CompleteCrafting = false;
[JsonProperty("Craft items with random skins if not already skinned")]
public bool RandomSkins = false;
[JsonProperty("Show Crafting Notes")]
public bool ShowCraftNotes = false;
[JsonProperty("Crafting rate bonus mulitplier (apply oxide perms for additional mulitpliers")]
public Dictionary<string, float> BonusMultiplier = new Dictionary<string, float>() { { "vip1", 90 }, { "vip2", 80 } };
[JsonProperty("Advanced Crafting Options")]
public Dictionary<string, CraftingData> CraftingOptions = new Dictionary<string, CraftingData>();
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null)
{
throw new JsonException();
}
if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys))
{
PrintToConsole("Configuration appears to be outdated; updating and saving");
SaveConfig();
}
}
catch
{
PrintToConsole($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig()
{
PrintToConsole($"Configuration changes saved to {Name}.json");
Config.WriteObject(config, true);
}
#endregion Config
#region Init
private const string perminstantbulkcraft = "craftingcontroller.instantbulkcraft";
private const string permblockitems = "craftingcontroller.blockitems";
private const string permitemrate = "craftingcontroller.itemrate";
private const string permcraftingrate = "craftingcontroller.craftingrate";
private const string permsetbenchlvl = "craftingcontroller.setbenchlvl";
private const string permsetskins = "craftingcontroller.setskins";
private List<string> permissions = new List<string> { perminstantbulkcraft, permblockitems, permitemrate, permcraftingrate, permsetbenchlvl, permsetskins };
private List<string> permissionsBonusMultiplier = new List<string>();
private List<string> commands = new List<string> { nameof(CommandCraftingRate), nameof(CommandCraftTime), nameof(CommandBlockItem), nameof(CommandUnblockItem), nameof(CommandSetDefaultSkin), nameof(CommandWorkbenchLVL) };
private void OnServerInitialized()
{
ItemManager.bpList.ForEach(bp => defaultsetup[bp.name] = bp.time);
config.BonusMultiplier.Keys.ToList().ForEach(perm => permissionsBonusMultiplier.Add("craftingcontroller." + perm));
//register permissions
permissions.ForEach(perm => permission.RegisterPermission(perm, this));
permissionsBonusMultiplier.ForEach(perm => permission.RegisterPermission(perm, this));
//register commands
commands.ForEach(command => AddLocalizedCommand(command));
if (config.SimpleMode)
{
Unsubscribe("OnItemCraft");
Unsubscribe("OnItemCraftFinished");
Unsubscribe("OnItemCraftCancelled");
}
var bplist = ItemManager.bpList.Where(item => config.CraftingOptions.ContainsKey(item.targetItem.shortname) == false).ToList();
bplist.ForEach(x => config.CraftingOptions.Add(x.targetItem.shortname, new CraftingData() { craftTime = x.time, workbenchLevel = x.workbenchLevelRequired }));
SaveConfig();
UpdateCraftingRate();
}
private void Unload()
{
ItemManager.bpList.ForEach(bp => bp.time = defaultsetup[bp.name]);
}
#endregion Init
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NoInvSpace"] = "You don't have enough room to craft this item!",
["NoPerms"] = "You don't have permission to use this command.",
["CannotFindItem"] = "Cannot find item {0}.",
["ItemBlocked"] = "{0} has been blocked from crafting.",
["ItemUnblocked"] = "{0} has been unblocked from crafting.",
["NeedsAdvancedOptions"] = "You need to enable advanced crafting options in your config to use this.",
["WrongNumberInput"] = "Your input needs to be a number.",
["ItemCraftTimeSet"] = "{0} craft time set to {1} seconds",
["WorkbenchLevelSet"] = "{0} workbench level set to {1}",
["CurrentCraftinRate"] = "The current crafting rate is {0 }%",
["CraftingRateUpdated"] = "The crafting rate was updated to {0} %",
["CraftTime2Args"] = "This command needs two arguments in the format /crafttime item.shortname timetocraft",
["BlockItem1Args"] = "This command needs one argument in the format /blockitem item.shortname",
["UnblockItem1Args"] = "This command needs one argument in the format /unblockitem item.shortname",
["WorckBenchLvl2Args"] = "This command needs two arguments in the format /benchlvl item.shortname workbenchlvl",
["BenchLevelInput"] = "The work bench level must be between 0 and 3",
["SetSkin2Args"] = "This command needs one argument in the format /setcraftskin item.shortname skinworkshopid",
["SkinSet"] = "The default skin for {0} was set to {1}",
["CraftTimeCheck"] = "The craft time of this item is {0}",
//Commands
["CommandCraftingRate"] = "craftrate",
["CommandCraftTime"] = "crafttime",
["CommandBlockItem"] = "blockitem",
["CommandUnblockItem"] = "unblockitem",
["CommandWorkbenchLVL"] = "benchlvl",
["CommandSetDefaultSkin"] = "setcraftskin"
}, this);
}
#endregion Localization
#region Commands
private void CommandCraftingRate(IPlayer iplayer, string command, string[] args)
{
if (!HasPerm(iplayer.Id, permitemrate))
{
Message(iplayer, "NoPerms");
return;
}
int craftingrate;
if (args.Length == 0)
{
Message(iplayer, "CurrentCraftinRate", config.CraftingRate);
return;
}
if (!int.TryParse(args[0], out craftingrate))
{
Message(iplayer, "WrongNumberInput");
return;
}
if (craftingrate < 0) craftingrate = 0;
config.CraftingRate = craftingrate;
UpdateCraftingRate();
Message(iplayer, "CraftingRateUpdated", config.CraftingRate);
if (config.SaveCommands) SaveConfig();
}
private void CommandCraftTime(IPlayer iplayer, string command, string[] args)
{
if (!HasPerm(iplayer.Id, permitemrate))
{
Message(iplayer, "NoPerms");
return;
}
if (args.Count() == 1)
{
var itemcheck = FindItem(args[0]);
if (itemcheck)
{
Message(iplayer, "CraftTimeCheck", itemcheck.Blueprint.time);
return;
}
}
if (args.Count() < 2)
{
Message(iplayer, "CraftTime2Args");
return;
}
var setitem = FindItem(args[0]);
if (!setitem)
{
Message(iplayer, "CannotFindItem", args[0]);
return;
}
if (args[1].ToLower() == "default")
{
config.CraftingOptions[setitem.shortname].useCrafteRateMultiplier = true;
config.CraftingOptions[setitem.shortname].craftTime = (defaultsetup[setitem.Blueprint.name] * (config.CraftingRate / 100));
Message(iplayer, "ItemCraftTimeSet", setitem.shortname, (setitem.Blueprint.time).ToString());
if (config.SaveCommands) SaveConfig();
return;
}
int crafttime;
if (!int.TryParse(args[1], out crafttime))
{
Message(iplayer, "WrongNumberInput");
return;
}
config.CraftingOptions[setitem.shortname].craftTime = crafttime;
config.CraftingOptions[setitem.shortname].useCrafteRateMultiplier = false;
var bp = ItemManager.bpList.Where(item => item.targetItem.shortname == setitem.shortname).FirstOrDefault();
bp.time = crafttime;
Message(iplayer, "ItemCraftTimeSet", setitem.shortname, crafttime.ToString());
if (config.SaveCommands) SaveConfig();
}
private void CommandBlockItem(IPlayer iplayer, string command, string[] args)
{
if (!HasPerm(iplayer.Id, permblockitems))
{
Message(iplayer, "NoPerms");
return;
}
if (args.Count() < 1)
{
Message(iplayer, "BlockItem1Args");
return;
}
var blockitem = FindItem(args[0]);
if (!blockitem)
{
Message(iplayer, "CannotFindItem", args[0]);
return;
}
config.CraftingOptions[blockitem.shortname].canCraft = false;
config.CraftingOptions[blockitem.shortname].canResearch = false;
var bp = ItemManager.bpList.Where(item => item.targetItem.shortname == blockitem.shortname).FirstOrDefault();
bp.userCraftable = false;
bp.isResearchable = false;
Message(iplayer, "ItemBlocked", blockitem.shortname);
if (config.SaveCommands) SaveConfig();
}
private void CommandUnblockItem(IPlayer iplayer, string command, string[] args)
{
if (!HasPerm(iplayer.Id, permblockitems))
{
Message(iplayer, "NoPerms");
return;
}
if (args.Count() < 1)
{
Message(iplayer, "UnbockItem1Args");
return;
}
var blockitem = FindItem(args[0]);
if (!blockitem)
{
Message(iplayer, "CannotFindItem", args[0]);
return;
}
config.CraftingOptions[blockitem.shortname].canCraft = true;
config.CraftingOptions[blockitem.shortname].canResearch = true;
var bp = ItemManager.bpList.Where(item => item.targetItem.shortname == blockitem.shortname).FirstOrDefault();
bp.userCraftable = true;
bp.isResearchable = true;
Message(iplayer, "ItemUnblocked", blockitem.shortname);
if (config.SaveCommands) SaveConfig();
}
private void CommandWorkbenchLVL(IPlayer iplayer, string command, string[] args)
{
if (!HasPerm(iplayer.Id, permsetbenchlvl))
{
Message(iplayer, "NoPerms");
return;
}
if (args.Count() < 2)
{
Message(iplayer, "WorckBenchLvl2Args");
return;
}
var item = FindItem(args[0]);
if (!item)
{
Message(iplayer, "CannotFindItem", args[0]);
return;
}
int benchlvl;
if (!int.TryParse(args[1], out benchlvl))
{
Message(iplayer, "WrongNumberInput");
return;
}
if (benchlvl < 0 || benchlvl > 3)
{
Message(iplayer, "BenchLevelInput");
return;
}
config.CraftingOptions[item.shortname].workbenchLevel = benchlvl;
var bp = ItemManager.bpList.Where(x => x.targetItem.shortname == item.shortname).FirstOrDefault();
bp.workbenchLevelRequired = benchlvl;
Message(iplayer, "WorkbenchLevelSet", item.shortname, benchlvl.ToString());
if (config.SaveCommands) SaveConfig();
}
private void CommandSetDefaultSkin(IPlayer iplayer, string command, string[] args)
{
if (!HasPerm(iplayer.Id, permsetskins))
{
Message(iplayer, "NoPerms");
return;
}
if (args.Count() < 2)
{
Message(iplayer, "SetSkin2Args");
return;
}
var setitem = FindItem(args[0]);
if (!setitem)
{
Message(iplayer, "CannotFindItem", args[0]);
return;
}
ulong skinid;
if (!ulong.TryParse(args[1], out skinid))
{
Message(iplayer, "WrongNumberInput", args);
return;
}
config.CraftingOptions[setitem.shortname].defaultskinid = skinid;
Message(iplayer, "SkinSet", setitem.shortname, skinid.ToString());
if (config.SaveCommands) SaveConfig();
}
#endregion Commands
#region Methods
private void UpdateCraftingRate()
{
foreach (var bp in ItemManager.bpList)
{
CraftingData data;
if (!config.CraftingOptions.TryGetValue(bp.targetItem.shortname, out data)) continue;
if (!data.canCraft)
{
bp.userCraftable = false;
continue;
}
if (!data.canResearch)
{
bp.isResearchable = false;
continue;
}
if (!data.useCrafteRateMultiplier)
{
bp.time = data.craftTime;
continue;
}
if (config.CraftingRate == 0f)
{
bp.time = 0f;
continue;
}
bp.time *= (float)(config.CraftingRate / 100);
if (data.workbenchLevel > -1 && data.workbenchLevel < 4)
bp.workbenchLevelRequired = data.workbenchLevel;
}
}
private void InstantBulkCraft(BasePlayer player, ItemCraftTask task, ItemDefinition item, List<int> stacks, int craftSkin, ulong skin)
{
if (skin == 0uL)
{
skin = ItemDefinition.FindSkin(item.itemid, craftSkin);
}
foreach (var stack in stacks)
{
var itemtogive = ItemManager.Create(item, stack, craftSkin != 0 && skin == 0uL ? (ulong)craftSkin : skin);
var held = itemtogive.GetHeldEntity();
if (held != null)
{
held.skinID = skin == 0uL ? (ulong)craftSkin : skin;
held.SendNetworkUpdate();
}
player.GiveItem(itemtogive);
if (config.ShowCraftNotes) player.Command(string.Concat(new object[] { "note.inv ", item.itemid, " ", stack }), new object[0]);
Interface.CallHook("OnItemCraftFinished", task, itemtogive);
}
}
private static void CompleteCrafting(BasePlayer player)
{
if (player.inventory.crafting.queue.Count == 0) return;
player.inventory.crafting.FinishCrafting(player.inventory.crafting.queue.First.Value);
player.inventory.crafting.queue.RemoveFirst();
}
private static void CancelAllCrafting(BasePlayer player)
{
var crafter = player.inventory.crafting;
crafter.queue.ToList().ForEach(x => crafter.CancelTask(x.taskUID, true));
}
#endregion Methods
#region Hooks
private Dictionary<ItemCraftTask, ulong> skinupdate = new Dictionary<ItemCraftTask, ulong>();
private object OnItemCraft(ItemCraftTask task, BasePlayer crafter)
{
var player = task.owner;
var target = task.blueprint.targetItem;
if (task.instanceData?.dataInt != null) return null;
var stacks = GetStacks(target, task.amount * task.blueprint.amountToCreate);
ulong defaultskin = 0uL;
int freeslots = FreeSlots(player);
if (!config.FullInventory && stacks.Count >= freeslots)
{
int space = FreeSpace(player, target);
if (space < 1)
{
ReturnCraft(task, player);
return false;
}
int taskamt = task.amount * task.blueprint.amountToCreate;
for (int i = 0; i < 20 && taskamt > space; i++)
{
var oldtaskamt = taskamt;
taskamt = space;
foreach (var item in task.takenItems)
{
var itemtogive = item;
double fraction = (double)taskamt / (double)oldtaskamt;
int amttogive = (int)(item.amount * (1 - fraction));
if (amttogive <= 1)
{
ReturnCraft(task, player);
return false;
}
itemtogive = ItemManager.Create(item.info, amttogive, 0uL);
item.amount -= amttogive;
player.GiveItem(itemtogive);
}
space -= (freeslots - FreeSlots(player)) * target.stackable;
if (space < 1 || taskamt < 1)
{
ReturnCraft(task, player);
return false;
}
if (taskamt <= space) break;
}
task.amount = (int)(taskamt / task.blueprint.amountToCreate);
}
if (task.skinID == 0)
{
CraftingData data;
if (config.CraftingOptions.TryGetValue(target.shortname, out data))
{
defaultskin = data.defaultskinid;
}
if (config.RandomSkins && defaultskin == 0)
{
var skins = GetSkins(ItemManager.FindItemDefinition(target.itemid));
defaultskin = skins.GetRandom();
}
if (defaultskin > 999999)
skinupdate[task] = defaultskin;
else
task.skinID = (int)defaultskin;
}
List<string> bonusperms = permissionsBonusMultiplier.Where(perm => HasPerm(player.UserIDString, perm)).ToList();
if (bonusperms.Count > 0)
{
task.blueprint.time *= (float)(config.BonusMultiplier[bonusperms.First().Split('.')[1].ToString()] / 100);
}
if (task.blueprint.time == 0f || HasPerm(player.UserIDString, perminstantbulkcraft))
{
skinupdate.Remove(task);
stacks = GetStacks(target, task.amount * task.blueprint.amountToCreate);
InstantBulkCraft(player, task, target, stacks, task.skinID, defaultskin);
task.cancelled = true;
return false;
}
return null;
}
private void OnItemCraftFinished(ItemCraftTask task, Item item)
{
ulong skinid;
if (!skinupdate.TryGetValue(task, out skinid)) return;
item.skin = skinid;
var held = item.GetHeldEntity();
if (held != null)
{
held.skinID = skinid;
held.SendNetworkUpdate();
}
if (task.amount == 0)
skinupdate.Remove(task);
}
void OnItemCraftCancelled(ItemCraftTask task)
{
ulong skinid;
if (!skinupdate.TryGetValue(task, out skinid)) return;
skinupdate.Remove(task);
}
private void OnServerQuit()
{
foreach (var player in BasePlayer.activePlayerList.Where(player => player.inventory.crafting.queue.Count > 0))
{
if (config.CompleteCrafting)
CompleteCrafting(player);
CancelAllCrafting(player);
}
}
#endregion Hooks
#region Helpers
private void ReturnCraft(ItemCraftTask task, BasePlayer crafter)
{
task.cancelled = true;
Message(crafter.IPlayer, "NoInvSpace");
foreach (var item in task.takenItems.Where(x => x.amount > 0)) task.owner.GiveItem(item);
}
private ItemDefinition FindItem(string itemNameOrId)
{
ItemDefinition itemDef = ItemManager.FindItemDefinition(itemNameOrId.ToLower());
if (itemDef == null)
{
int itemId;
if (int.TryParse(itemNameOrId, out itemId))
{
itemDef = ItemManager.FindItemDefinition(itemId);
}
}
return itemDef;
}
private int FreeSpace(BasePlayer player, ItemDefinition item)
{
var slots = player.inventory.containerMain.capacity + player.inventory.containerBelt.capacity;
List<Item> containeritems = new List<Item>();
Dictionary<ItemDefinition, int> queueamts = new Dictionary<ItemDefinition, int>();
containeritems.AddRange(player.inventory.containerMain.itemList);
containeritems.AddRange(player.inventory.containerBelt.itemList);
int value = 0;
//Sum all items in crafting queue not including the item to be crafted
foreach (var queueitem in player.inventory.crafting.queue)
{
if (queueitem.blueprint.targetItem == item) continue;
if (queueamts.TryGetValue(queueitem.blueprint.targetItem, out value))
{
queueamts[queueitem.blueprint.targetItem] += queueitem.amount * queueitem.blueprint.amountToCreate;
continue;
}
queueamts[queueitem.blueprint.targetItem] = (queueitem.amount * queueitem.blueprint.amountToCreate);
}
//Take into account room of other stacks
int queuestacks = 0;
queueamts.ToList().ForEach(i => queuestacks += GetStacks(i.Key, i.Value - Stackroom(containeritems, i.Key.shortname)).Count);
//calculate total room in inventory for the item required
int invstackroom = (slots - containeritems.Count - queuestacks) * item.stackable;
invstackroom += containeritems.Where(x => x.info == item && x.amount < x.MaxStackable()).Sum(x => x.MaxStackable() - x.amount);
invstackroom -= player.inventory.crafting.queue.ToList().Where(x => x.blueprint.targetItem.shortname == item.shortname).Sum(x => x.amount * x.blueprint.amountToCreate);
return invstackroom;
}
private int FreeSlots(BasePlayer player)
{
var slots = player.inventory.containerMain.capacity + player.inventory.containerBelt.capacity;
var taken = player.inventory.containerMain.itemList.Count + player.inventory.containerBelt.itemList.Count;
return slots - taken;
}
private int Stackroom(List<Item> items, string item)
{
return items.Where(x => x.info.shortname == item && x.amount < x.MaxStackable()).Sum(x => x.MaxStackable() - x.amount);
}
private List<int> GetStacks(ItemDefinition item, int amount)
{
var list = new List<int>();
var maxStack = item.stackable;
while (amount > maxStack)
{
amount -= maxStack;
list.Add(maxStack);
}
list.Add(amount);
return list;
}
private readonly Dictionary<string, List<ulong>> skinsCache = new Dictionary<string, List<ulong>>();
private List<ulong> GetSkins(ItemDefinition def)
{
List<ulong> skins;
if (skinsCache.TryGetValue(def.shortname, out skins)) return skins;
skins = new List<ulong>();
skins.AddRange(ItemSkinDirectory.ForItem(def).Select(skin => (ulong)skin.id));
skins.AddRange(Rust.Workshop.Approved.All.Values.Where(skin => skin.Skinnable.ItemName == def.shortname).Select(skin => skin.WorkshopdId));
skinsCache.Add(def.shortname, skins);
return skins;
}
private string GetLang(string langKey, string playerId = null, params object[] args)
{
return string.Format(lang.GetMessage(langKey, this, playerId), args);
}
private void Message(IPlayer player, string langKey, params object[] args)
{
if (player.IsConnected) player.Message(GetLang(langKey, player.Id, args));
}
private bool HasPerm(string id, string perm) => permission.UserHasPermission(id, perm);
private void AddLocalizedCommand(string command)
{
foreach (string language in lang.GetLanguages(this))
{
Dictionary<string, string> messages = lang.GetMessages(language, this);
foreach (KeyValuePair<string, string> message in messages)
{
if (!message.Key.Equals(command)) continue;
if (string.IsNullOrEmpty(message.Value)) continue;
AddCovalenceCommand(message.Value, command);
}
}
}
#endregion Helpers
}
}

513
plugins/DiscordAuth.cs Normal file
View File

@ -0,0 +1,513 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Ext.Discord;
using Oxide.Ext.Discord.Attributes;
using Oxide.Ext.Discord.DiscordObjects;
namespace Oxide.Plugins
{
[Info("Discord Auth", "Tricky", "1.1.3")]
[Description("Allows players to connect their discord account with steam")]
public class DiscordAuth : CovalencePlugin
{
#region Defined
[DiscordClient]
private DiscordClient Client;
#endregion
#region Config
Configuration config;
class Configuration
{
[JsonProperty(PropertyName = "Settings")]
public Settings Info = new Settings();
[JsonProperty(PropertyName = "Authentication Code")]
public AuthCode Code = new AuthCode();
public class Settings
{
[JsonProperty(PropertyName = "Bot Token")]
public string BotToken = string.Empty;
[JsonProperty(PropertyName = "Oxide Group")]
public string Group = "authenticated";
[JsonProperty(PropertyName = "Enable Logging")]
public bool Log = false;
[JsonProperty(PropertyName = "Auth Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] AuthCommands = new string[] { "auth", "authenticate" };
[JsonProperty(PropertyName = "Deauth Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] DeauthCommands = new string[] { "deauth", "deauthenticate" };
[JsonProperty(PropertyName = "Discord Roles to Assign", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> Roles = new List<string>()
{
"Authenticated"
};
[JsonProperty(PropertyName = "Revoke Oxide Group on Discord Leave")]
public bool RemovefromGroup = true;
[JsonProperty(PropertyName = "Deauthenticate on Discord Leave")]
public bool Deauthenticate = false;
[JsonProperty(PropertyName = "Chat Prefix")]
public string ChatPrefix = "[#1874CD](Auth)[/#]:";
}
public class AuthCode
{
[JsonProperty(PropertyName = "Code Lifetime (minutes)")]
public int CodeLifetime = 60;
[JsonProperty(PropertyName = "Code Length")]
public int CodeLength = 5;
[JsonProperty(PropertyName = "Lowercase")]
public bool Lowercase = false;
}
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null) throw new Exception();
}
catch
{
Config.WriteObject(config, false, $"{Interface.Oxide.ConfigDirectory}/{Name}.jsonError");
PrintError("The configuration file contains an error and has been replaced with a default config.\n" +
"The error configuration file was saved in the .jsonError extension");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Classes and Stored Data
private enum MemberRole { Add, Remove }
private const string authPerm = "discordauth.auth";
private const string deauthPerm = "discordauth.deauth";
private Data data;
private class Data
{
public Dictionary<string, string> Players = new Dictionary<string, string>();
}
private Dictionary<string, string> Codes = new Dictionary<string, string>();
#endregion
#region Lang
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Code Generation"] = "Here is your code: [#1874CD]{0}[/#]\nJoin our [#EE3B3B]Discord[/#] and PM the code to the Discord Bot",
["Code Expired"] = "Your code has [#EE3B3B]Expired![/#]",
["Authenticated"] = "Thank you for authenticating your account",
["Game-Deauthenticated"] = "Successfully deauthenticated your account",
["Discord-Deauthenticated"] = "You have been deauthenticated from {0}",
["Already Authenticated"] = "You have already [#1874CD]authenticated[/#] your account, no need to do it again",
["Not Authenticated"] = "You are not authenticated",
["Group Revoked"] = "Your '{0}' Group has been revoked! Join the server back to achieve it",
["Group Granted"] = "Granted '{0}' Group and the discord roles for joining {1} back",
["Unable to find code"] = "Sorry, we couldn't find your code, please try to authenticate again, If you haven't generated a code, please type /auth in-game",
["No Permission"] = "You dont have permission to use this command"
}, this);
}
#endregion
#region Commands
private void AuthCommand(IPlayer player, string command, string[] args)
{
// No Permission
if (!player.HasPermission(authPerm))
{
Message(player, "No Permission");
return;
}
// Already authenticated-check
if (data.Players.ContainsKey(player.Id))
{
Message(player, "Already Authenticated");
return;
}
// Sends the code if already exist to prevent duplication
if (Codes.ContainsKey(player.Id))
{
Message(player, "Code Generation", Codes[player.Id]);
return;
}
// Adds a random code and send it to the player if doesn't already exist
var code = GenerateCode(config.Code.CodeLength, config.Code.Lowercase);
Codes.Add(player.Id, code);
Message(player, "Code Generation", code);
// Code Expiration Function
timer.In(config.Code.CodeLifetime * 60, () =>
{
if (Codes.ContainsKey(player.Id))
{
Codes.Remove(player.Id);
if (player != null) Message(player, "Code Expired");
}
});
}
private void DeauthCommand(IPlayer player, string command, string[] args)
{
// No Permission
if (!player.HasPermission(deauthPerm))
{
Message(player, "No Permission");
return;
}
if (!data.Players.ContainsKey(player.Id))
{
Message(player, "Not Authenticated");
return;
}
Oxide.Ext.Discord.DiscordObjects.User.GetUser(Client, data.Players[player.Id], user => HandleRoles(user, MemberRole.Remove));
Deauthenticate(player.Id, data.Players[player.Id]);
Message(player, "Game-Deauthenticated");
}
#endregion
#region Oxide Hooks
private void Init()
{
data = Interface.Oxide.DataFileSystem.ReadObject<Data>(Name);
CreateClient();
AddCovalenceCommand(config.Info.AuthCommands, nameof(AuthCommand));
AddCovalenceCommand(config.Info.DeauthCommands, nameof(DeauthCommand));
permission.CreateGroup(config.Info.Group, config.Info.Group, 0);
permission.RegisterPermission(authPerm, this);
permission.RegisterPermission(deauthPerm, this);
if (!config.Info.Deauthenticate && !config.Info.RemovefromGroup)
Unsubscribe(nameof(Discord_MemberRemoved));
if (!config.Info.RemovefromGroup)
Unsubscribe(nameof(Discord_MemberAdded));
if (!config.Info.Log)
Unsubscribe(nameof(DiscordSocket_Initalized));
}
private void Unload()
{
CloseClient();
SaveData();
}
private void OnServerSave() => SaveData();
#endregion
#region Discord Hooks
// Called when a message is created on the Discord server
private void Discord_MessageCreate(Message message)
{
// Bot-check
if (message.author.bot == true)
return;
Channel.GetChannel(Client, message.channel_id, dm =>
{
// DM-check
if (dm.type != ChannelType.DM)
return;
// Length-check
if (message.content.Length != config.Code.CodeLength)
return;
// No code found
if (!Codes.ContainsValue(message.content))
{
dm.CreateMessage(Client, GetEmbed(Formatter.ToPlaintext(Lang("Unable to find code")), 16098851));
return;
}
// Already authenticated-check
if (data.Players.ContainsValue(message.author.id))
{
dm.CreateMessage(Client, GetEmbed(Formatter.ToPlaintext(Lang("Already Authenticated")), 4886754));
return;
}
Codes.Keys.ToList().ForEach(playerId =>
{
if (Codes[playerId] != message.content)
return;
Authenticate(playerId, message.author.id);
});
HandleRoles(message.author, MemberRole.Add);
dm.CreateMessage(Client, GetEmbed(Formatter.ToPlaintext(Lang("Authenticated")), 11523722));
});
}
// Called when a member leaves the Discord server
private void Discord_MemberRemoved(GuildMember member)
{
var steamId = API_GetSteam(member.user.id);
// No user found
if (steamId == null)
return;
if (config.Info.Deauthenticate)
{
Deauthenticate(steamId, member.user.id);
member.user.CreateDM(Client, dm => dm.CreateMessage(Client, GetEmbed(Formatter.ToPlaintext(Lang("Discord-Deauthenticated", steamId, Client.DiscordServer.name)), 9905970)));
return;
}
if (config.Info.RemovefromGroup)
{
permission.RemoveUserGroup(steamId, config.Info.Group);
member.user.CreateDM(Client, dm => dm.CreateMessage(Client, GetEmbed(Formatter.ToPlaintext(Lang("Group Revoked", steamId, config.Info.Group)), 16098851)));
}
}
// Called when a user joins the discord server
private void Discord_MemberAdded(GuildMember member)
{
var steamId = API_GetSteam(member.user.id);
// No user found
if (steamId == null)
return;
HandleRoles(member.user, MemberRole.Add);
permission.AddUserGroup(steamId, config.Info.Group);
member.user.CreateDM(Client, dm => dm.CreateMessage(Client, GetEmbed(Formatter.ToPlaintext(Lang("Group Granted", steamId, config.Info.Group, Client.DiscordServer.name)), 4886754)));
}
// Called when the client is created, and the plugin can use it
private void DiscordSocket_Initalized(DiscordClient client) => Puts("Discord Initalized!");
#endregion
#region Core
private void Authenticate(string steamId, string discordId)
{
if (Interface.Oxide.CallHook("OnAuthenticate", steamId, discordId) != null)
return;
data.Players.Add(steamId, discordId);
permission.AddUserGroup(steamId, config.Info.Group);
}
private void Deauthenticate(string steamId, string discordId)
{
if (Interface.Oxide.CallHook("OnDeauthenticate", steamId, discordId) != null)
return;
data.Players.Remove(steamId);
permission.RemoveUserGroup(steamId, config.Info.Group);
}
private void HandleRoles(Oxide.Ext.Discord.DiscordObjects.User user, MemberRole memberRole)
{
config.Info.Roles.ForEach(roleName =>
{
var role = GetRoleByName(roleName);
if (role == null)
{
PrintError($"Unable to find '{roleName}'");
return;
}
switch (memberRole)
{
case MemberRole.Add:
Client.DiscordServer.AddGuildMemberRole(Client, user, role);
break;
case MemberRole.Remove:
Client.DiscordServer.RemoveGuildMemberRole(Client, user, role);
break;
}
});
}
#endregion
#region API
//private bool API_Authenticate(string steamId, string discordId, bool addtoGroup = true, bool callHook = true)
//{
// if (!data.Players.ContainsKey(steamId) || !data.Players.ContainsValue(discordId))
// {
// if(addtoGroup)
// permission.AddUserGroup(steamId, config.Info.Group);
// if(callHook)
// Interface.Oxide.CallHook("OnAuthenticate", steamId, discordId);
// data.Players.Add(steamId, discordId);
// return true;
// }
// return false;
//}
//private bool API_Deauthenticate(string Id, bool removefromGroup = true, bool callHook = true)
//{
// // If Id is steamId
// if (data.Players.ContainsKey(Id))
// {
// if (removefromGroup)
// permission.RemoveUserGroup(Id, config.Info.Group);
// if (callHook)
// Interface.Oxide.CallHook("OnDeauthenticate", Id, data.Players[Id]);
// data.Players.Remove(Id);
// return true;
// }
// // If Id is discordId
// if (data.Players.ContainsValue(Id))
// {
// foreach (var steamid in data.Players.Keys)
// {
// if (data.Players[steamid] == Id)
// {
// if (removefromGroup)
// permission.RemoveUserGroup(steamid, config.Info.Group);
// if (callHook)
// Interface.Oxide.CallHook("OnDeauthenticate", steamid, Id);
// data.Players.Remove(steamid);
// return true;
// }
// }
// }
// return false;
//}
private bool API_IsAuthenticated(string Id)
{
if (data.Players.ContainsKey(Id))
return true;
if (data.Players.ContainsValue(Id))
return true;
return false;
}
private string API_GetSteam(string Id)
{
if (data.Players.ContainsValue(Id))
{
foreach (var steamid in data.Players.Keys)
{
if (data.Players[steamid] == Id)
return steamid;
}
}
return null;
}
private string API_GetDiscord(string Id)
{
if (data.Players.ContainsKey(Id))
{
return data.Players[Id];
}
return null;
}
private int API_GetAuthCount() => data.Players.Count;
private List<string> API_GetSteamList() => data.Players.Keys.ToList();
private List<string> API_GetDiscordList() => data.Players.Values.ToList();
#endregion
#region Helpers
private void CreateClient()
{
if (config.Info.BotToken != string.Empty)
Discord.CreateClient(this, config.Info.BotToken);
}
private void CloseClient() => Discord.CloseClient(Client);
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, data);
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
private void Message(IPlayer player, string key, params object[] args) => player.Reply($"{config.Info.ChatPrefix} {Lang(key, player.Id, args)}");
private string GenerateCode(int size, bool lowerCase)
{
var builder = new StringBuilder();
var random = new System.Random();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
if (lowerCase)
return builder.ToString().ToLower();
return builder.ToString();
}
private Embed GetEmbed(string text, int color)
{
var embed = new Embed
{
description = text,
color = color
};
return embed;
}
private Role GetRoleByName(string roleName)
{
foreach (var role in Client.DiscordServer.roles)
{
if (role.name == roleName)
return role;
}
return null;
}
#endregion
}
}

721
plugins/GatherManager.cs Normal file
View File

@ -0,0 +1,721 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Gathering Manager", "Mughisi", "2.2.75", ResourceId = 675)]
class GatherManager : RustPlugin
{
#region Configuration Data
// Do not modify these values because this will not change anything, the values listed below are only used to create
// the initial configuration file. If you wish changes to the configuration file you should edit 'GatherManager.json'
// which is located in your server's config folder: <drive>:\...\server\<your_server_identity>\oxide\config\
private bool configChanged;
// Plugin settings
private const string DefaultChatPrefix = "Gather Manager";
private const string DefaultChatPrefixColor = "#008000ff";
public string ChatPrefix { get; private set; }
public string ChatPrefixColor { get; private set; }
// Plugin options
private static readonly Dictionary<string, object> DefaultGatherResourceModifiers = new Dictionary<string, object>();
private static readonly Dictionary<string, object> DefaultGatherDispenserModifiers = new Dictionary<string, object>();
private static readonly Dictionary<string, object> DefaultQuarryResourceModifiers = new Dictionary<string, object>();
private static readonly Dictionary<string, object> DefaultPickupResourceModifiers = new Dictionary<string, object>();
private static readonly Dictionary<string, object> DefaultSurveyResourceModifiers = new Dictionary<string, object>();
// Defaults
private const float DefaultMiningQuarryResourceTickRate = 5f;
private const float DefaultExcavatorResourceTickRate = 3f;
private const float DefaultExcavatorTimeForFullResources = 120f;
private const float DefaultExcavatorBeltSpeedMax = 0.1f;
public Dictionary<string, float> GatherResourceModifiers { get; private set; }
public Dictionary<string, float> GatherDispenserModifiers { get; private set; }
public Dictionary<string, float> QuarryResourceModifiers { get; private set; }
public Dictionary<string, float> ExcavatorResourceModifiers { get; private set; }
public Dictionary<string, float> PickupResourceModifiers { get; private set; }
public Dictionary<string, float> SurveyResourceModifiers { get; private set; }
public float MiningQuarryResourceTickRate { get; private set; }
public float ExcavatorResourceTickRate { get; private set; }
public float ExcavatorTimeForFullResources { get; private set; }
public float ExcavatorBeltSpeedMax { get; private set; }
// Plugin messages
private const string DefaultNotAllowed = "You don't have permission to use this command.";
private const string DefaultInvalidArgumentsGather =
"Invalid arguments supplied! Use gather.rate <type:dispenser|pickup|quarry|survey> <resource> <multiplier>";
private const string DefaultInvalidArgumentsDispenser =
"Invalid arguments supplied! Use dispenser.scale <dispenser:tree|ore|corpse> <multiplier>";
private const string DefaultInvalidArgumentsSpeed =
"Invalid arguments supplied! Use quarry.rate <time between gathers in seconds>";
private const string DefaultInvalidModifier =
"Invalid modifier supplied! The new modifier always needs to be bigger than 0!";
private const string DefaultInvalidSpeed = "You can't set the speed lower than 1 second!";
private const string DefaultModifyResource = "You have set the gather rate for {0} to x{1} from {2}.";
private const string DefaultModifyResourceRemove = "You have reset the gather rate for {0} from {1}.";
private const string DefaultModifySpeed = "The Mining Quarry will now provide resources every {0} seconds.";
private const string DefaultInvalidResource =
"{0} is not a valid resource. Check gather.resources for a list of available options.";
private const string DefaultModifyDispenser = "You have set the resource amount for {0} dispensers to x{1}";
private const string DefaultInvalidDispenser =
"{0} is not a valid dispenser. Check gather.dispensers for a list of available options.";
private const string DefaultHelpText = "/gather - Shows you detailed gather information.";
private const string DefaultHelpTextPlayer = "Resources gained from gathering have been scaled to the following:";
private const string DefaultHelpTextAdmin = "To change the resources gained by gathering use the command:\r\ngather.rate <type:dispenser|pickup|quarry|survey> <resource> <multiplier>\r\nTo change the amount of resources in a dispenser type use the command:\r\ndispenser.scale <dispenser:tree|ore|corpse> <multiplier>\r\nTo change the time between Mining Quarry gathers:\r\nquarry.tickrate <seconds>";
private const string DefaultHelpTextPlayerGains = "Resources gained from {0}:";
private const string DefaultHelpTextPlayerMiningQuarrySpeed = "Time between Mining Quarry gathers: {0} second(s).";
private const string DefaultHelpTextPlayerDefault = "Default values.";
private const string DefaultDispensers = "Resource Dispensers";
private const string DefaultCharges = "Survey Charges";
private const string DefaultQuarries = "Mining Quarries";
private const string DefaultExcavators = "Excavators";
private const string DefaultPickups = "pickups";
public string NotAllowed { get; private set; }
public string InvalidArgumentsGather { get; private set; }
public string InvalidArgumentsDispenser { get; private set; }
public string InvalidArgumentsSpeed { get; private set; }
public string InvalidModifier { get; private set; }
public string InvalidSpeed { get; private set; }
public string ModifyResource { get; private set; }
public string ModifyResourceRemove { get; private set; }
public string ModifySpeed { get; private set; }
public string InvalidResource { get; private set; }
public string ModifyDispenser { get; private set; }
public string InvalidDispenser { get; private set; }
public string HelpText { get; private set; }
public string HelpTextPlayer { get; private set; }
public string HelpTextAdmin { get; private set; }
public string HelpTextPlayerGains { get; private set; }
public string HelpTextPlayerDefault { get; private set; }
public string HelpTextPlayerMiningQuarrySpeed { get; private set; }
public string Dispensers { get; private set; }
public string Charges { get; private set; }
public string Quarries { get; private set; }
public string Excavators { get; private set; }
public string Pickups { get; private set; }
#endregion
private readonly List<string> subcommands = new List<string>() { "dispenser", "pickup", "quarry", "survey" };
private readonly Hash<string, ItemDefinition> validResources = new Hash<string, ItemDefinition>();
private readonly Hash<string, ResourceDispenser.GatherType> validDispensers = new Hash<string, ResourceDispenser.GatherType>();
private void Init() => LoadConfigValues();
private void OnServerInitialized()
{
var resourceDefinitions = ItemManager.itemList;
foreach (var def in resourceDefinitions.Where(def => def.category == ItemCategory.Food || def.category == ItemCategory.Resources))
validResources.Add(def.displayName.english.ToLower(), def);
validDispensers.Add("tree", ResourceDispenser.GatherType.Tree);
validDispensers.Add("ore", ResourceDispenser.GatherType.Ore);
validDispensers.Add("corpse", ResourceDispenser.GatherType.Flesh);
validDispensers.Add("flesh", ResourceDispenser.GatherType.Flesh);
foreach (var excavator in UnityEngine.Object.FindObjectsOfType<ExcavatorArm>())
{
if (ExcavatorResourceTickRate != DefaultMiningQuarryResourceTickRate)
{
excavator.CancelInvoke("ProcessResources");
excavator.InvokeRepeating("ProcessResources", ExcavatorResourceTickRate, ExcavatorResourceTickRate);
}
if (ExcavatorBeltSpeedMax != DefaultExcavatorBeltSpeedMax)
{
excavator.beltSpeedMax = ExcavatorBeltSpeedMax;
}
if (ExcavatorTimeForFullResources != DefaultExcavatorTimeForFullResources)
{
excavator.timeForFullResources = ExcavatorTimeForFullResources;
}
}
}
private void Unload()
{
foreach (var excavator in UnityEngine.Object.FindObjectsOfType<ExcavatorArm>())
{
if (ExcavatorResourceTickRate != DefaultMiningQuarryResourceTickRate)
{
excavator.CancelInvoke("ProcessResources");
excavator.InvokeRepeating("ProcessResources", DefaultMiningQuarryResourceTickRate, DefaultMiningQuarryResourceTickRate);
}
if (ExcavatorBeltSpeedMax != DefaultExcavatorBeltSpeedMax)
{
excavator.beltSpeedMax = DefaultExcavatorBeltSpeedMax;
}
if (ExcavatorTimeForFullResources != DefaultExcavatorTimeForFullResources)
{
excavator.timeForFullResources = DefaultExcavatorTimeForFullResources;
}
}
}
protected override void LoadDefaultConfig() => PrintWarning("New configuration file created.");
[ChatCommand("gather")]
private void Gather(BasePlayer player, string command, string[] args)
{
var help = HelpTextPlayer;
if (GatherResourceModifiers.Count == 0 && SurveyResourceModifiers.Count == 0 && PickupResourceModifiers.Count == 0 && QuarryResourceModifiers.Count == 0)
help += HelpTextPlayerDefault;
else
{
if (GatherResourceModifiers.Count > 0)
{
var dispensers = string.Format(HelpTextPlayerGains, Dispensers);
dispensers = GatherResourceModifiers.Aggregate(dispensers, (current, entry) => current + ("\r\n " + entry.Key + ": x" + entry.Value));
help += "\r\n" + dispensers;
}
if (PickupResourceModifiers.Count > 0)
{
var pickups = string.Format(HelpTextPlayerGains, Pickups);
pickups = PickupResourceModifiers.Aggregate(pickups, (current, entry) => current + ("\r\n " + entry.Key + ": x" + entry.Value));
help += "\r\n" + pickups;
}
if (QuarryResourceModifiers.Count > 0)
{
var quarries = string.Format(HelpTextPlayerGains, Quarries);
quarries = QuarryResourceModifiers.Aggregate(quarries, (current, entry) => current + ("\r\n " + entry.Key + ": x" + entry.Value));
help += "\r\n" + quarries;
}
if (ExcavatorResourceModifiers.Count > 0)
{
var excavators = string.Format(HelpTextPlayerGains, Excavators);
excavators = ExcavatorResourceModifiers.Aggregate(excavators, (current, entry) => current + ("\r\n " + entry.Key + ": x" + entry.Value));
help += "\r\n" + excavators;
}
if (SurveyResourceModifiers.Count > 0)
{
var charges = string.Format(HelpTextPlayerGains, Charges);
charges = SurveyResourceModifiers.Aggregate(charges, (current, entry) => current + ("\r\n " + entry.Key + ": x" + entry.Value));
help += "\r\n" + charges;
}
}
if (MiningQuarryResourceTickRate != DefaultMiningQuarryResourceTickRate)
help += "\r\n" + string.Format(HelpTextPlayerMiningQuarrySpeed, MiningQuarryResourceTickRate);
SendMessage(player, help);
if (!player.IsAdmin) return;
SendMessage(player, HelpTextAdmin);
}
private void SendHelpText(BasePlayer player) => SendMessage(player, HelpText);
[ConsoleCommand("gather.rate")]
private void GatherRate(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !arg.Player().IsAdmin)
{
arg.ReplyWith(NotAllowed);
return;
}
var subcommand = arg.GetString(0).ToLower();
if (!arg.HasArgs(3) || !subcommands.Contains(subcommand))
{
arg.ReplyWith(InvalidArgumentsGather);
return;
}
if (!validResources[arg.GetString(1).ToLower()] && arg.GetString(1) != "*")
{
arg.ReplyWith(string.Format(InvalidResource, arg.GetString(1)));
return;
}
var resource = validResources[arg.GetString(1).ToLower()]?.displayName.english ?? "*";
var modifier = arg.GetFloat(2, -1);
var remove = false;
if (modifier < 0)
{
if (arg.GetString(2).ToLower() == "remove")
remove = true;
else
{
arg.ReplyWith(InvalidModifier);
return;
}
}
switch (subcommand)
{
case "dispenser":
if (remove)
{
if (GatherResourceModifiers.ContainsKey(resource))
GatherResourceModifiers.Remove(resource);
arg.ReplyWith(string.Format(ModifyResourceRemove, resource, Dispensers));
}
else
{
if (GatherResourceModifiers.ContainsKey(resource))
GatherResourceModifiers[resource] = modifier;
else
GatherResourceModifiers.Add(resource, modifier);
arg.ReplyWith(string.Format(ModifyResource, resource, modifier, Dispensers));
}
SetConfigValue("Options", "GatherResourceModifiers", GatherResourceModifiers);
break;
case "pickup":
if (remove)
{
if (PickupResourceModifiers.ContainsKey(resource))
PickupResourceModifiers.Remove(resource);
arg.ReplyWith(string.Format(ModifyResourceRemove, resource, Pickups));
}
else
{
if (PickupResourceModifiers.ContainsKey(resource))
PickupResourceModifiers[resource] = modifier;
else
PickupResourceModifiers.Add(resource, modifier);
arg.ReplyWith(string.Format(ModifyResource, resource, modifier, Pickups));
}
SetConfigValue("Options", "PickupResourceModifiers", PickupResourceModifiers);
break;
case "quarry":
if (remove)
{
if (QuarryResourceModifiers.ContainsKey(resource))
QuarryResourceModifiers.Remove(resource);
arg.ReplyWith(string.Format(ModifyResourceRemove, resource, Quarries));
}
else
{
if (QuarryResourceModifiers.ContainsKey(resource))
QuarryResourceModifiers[resource] = modifier;
else
QuarryResourceModifiers.Add(resource, modifier);
arg.ReplyWith(string.Format(ModifyResource, resource, modifier, Quarries));
}
SetConfigValue("Options", "QuarryResourceModifiers", QuarryResourceModifiers);
break;
case "excavator":
if (remove)
{
if (ExcavatorResourceModifiers.ContainsKey(resource))
ExcavatorResourceModifiers.Remove(resource);
arg.ReplyWith(string.Format(ModifyResourceRemove, resource, Excavators));
}
else
{
if (ExcavatorResourceModifiers.ContainsKey(resource))
ExcavatorResourceModifiers[resource] = modifier;
else
ExcavatorResourceModifiers.Add(resource, modifier);
arg.ReplyWith(string.Format(ModifyResource, resource, modifier, Excavators));
}
SetConfigValue("Options", "ExcavatorResourceModifiers", ExcavatorResourceModifiers);
break;
case "survey":
if (remove)
{
if (SurveyResourceModifiers.ContainsKey(resource))
SurveyResourceModifiers.Remove(resource);
arg.ReplyWith(string.Format(ModifyResourceRemove, resource, Charges));
}
else
{
if (SurveyResourceModifiers.ContainsKey(resource))
SurveyResourceModifiers[resource] = modifier;
else
SurveyResourceModifiers.Add(resource, modifier);
arg.ReplyWith(string.Format(ModifyResource, resource, modifier, Charges));
}
SetConfigValue("Options", "SurveyResourceModifiers", SurveyResourceModifiers);
break;
}
}
[ConsoleCommand("gather.resources")]
private void GatherResources(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !arg.Player().IsAdmin)
{
arg.ReplyWith(NotAllowed);
return;
}
arg.ReplyWith(validResources.Aggregate("Available resources:\r\n", (current, resource) => current + (resource.Value.displayName.english + "\r\n")) + "* (For all resources that are not setup separately)");
}
[ConsoleCommand("gather.dispensers")]
private void GatherDispensers(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !arg.Player().IsAdmin)
{
arg.ReplyWith(NotAllowed);
return;
}
arg.ReplyWith(validDispensers.Aggregate("Available dispensers:\r\n", (current, dispenser) => current + (dispenser.Value.ToString("G") + "\r\n")));
}
[ConsoleCommand("dispenser.scale")]
private void DispenserRate(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !arg.Player().IsAdmin)
{
arg.ReplyWith(NotAllowed);
return;
}
if (!arg.HasArgs(2))
{
arg.ReplyWith(InvalidArgumentsDispenser);
return;
}
if (!validDispensers.ContainsKey(arg.GetString(0).ToLower()))
{
arg.ReplyWith(string.Format(InvalidDispenser, arg.GetString(0)));
return;
}
var dispenser = validDispensers[arg.GetString(0).ToLower()].ToString("G");
var modifier = arg.GetFloat(1, -1);
if (modifier < 0)
{
arg.ReplyWith(InvalidModifier);
return;
}
if (GatherDispenserModifiers.ContainsKey(dispenser))
GatherDispenserModifiers[dispenser] = modifier;
else
GatherDispenserModifiers.Add(dispenser, modifier);
SetConfigValue("Options", "GatherDispenserModifiers", GatherDispenserModifiers);
arg.ReplyWith(string.Format(ModifyDispenser, dispenser, modifier));
}
[ConsoleCommand("quarry.tickrate")]
private void MiningQuarryTickRate(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !arg.Player().IsAdmin)
{
arg.ReplyWith(NotAllowed);
return;
}
if (!arg.HasArgs())
{
arg.ReplyWith(InvalidArgumentsSpeed);
return;
}
var modifier = arg.GetFloat(0, -1);
if (modifier < 1)
{
arg.ReplyWith(InvalidSpeed);
return;
}
MiningQuarryResourceTickRate = modifier;
SetConfigValue("Options", "MiningQuarryResourceTickRate", MiningQuarryResourceTickRate);
arg.ReplyWith(string.Format(ModifySpeed, modifier));
var quarries = UnityEngine.Object.FindObjectsOfType<MiningQuarry>();
foreach (var quarry in quarries.Where(quarry => quarry.IsOn()))
{
quarry.CancelInvoke("ProcessResources");
quarry.InvokeRepeating("ProcessResources", MiningQuarryResourceTickRate, MiningQuarryResourceTickRate);
}
}
[ConsoleCommand("excavator.tickrate")]
private void ExcavatorTickRate(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !arg.Player().IsAdmin)
{
arg.ReplyWith(NotAllowed);
return;
}
if (!arg.HasArgs())
{
arg.ReplyWith(InvalidArgumentsSpeed);
return;
}
var modifier = arg.GetFloat(0, -1);
if (modifier < 1)
{
arg.ReplyWith(InvalidSpeed);
return;
}
ExcavatorResourceTickRate = modifier;
SetConfigValue("Options", "ExcavatorResourceTickRate", ExcavatorResourceTickRate);
arg.ReplyWith(string.Format(ModifySpeed, modifier));
var excavators = UnityEngine.Object.FindObjectsOfType<MiningQuarry>();
foreach (var excavator in excavators.Where(excavator => excavator.IsOn()))
{
excavator.CancelInvoke("ProcessResources");
excavator.InvokeRepeating("ProcessResources", ExcavatorResourceTickRate, ExcavatorResourceTickRate);
}
}
private void OnDispenserGather(ResourceDispenser dispenser, BaseEntity entity, Item item)
{
if (!entity.ToPlayer())
{
return;
}
var gatherType = dispenser.gatherType.ToString("G");
var amount = item.amount;
float modifier;
if (GatherResourceModifiers.TryGetValue(item.info.displayName.english, out modifier))
{
item.amount = (int)(item.amount * modifier);
}
else if (GatherResourceModifiers.TryGetValue("*", out modifier))
{
item.amount = (int)(item.amount * modifier);
}
if (!GatherResourceModifiers.ContainsKey(gatherType))
{
return;
}
var dispenserModifier = GatherDispenserModifiers[gatherType];
try
{
dispenser.containedItems.Single(x => x.itemid == item.info.itemid).amount += amount - item.amount / dispenserModifier;
if (dispenser.containedItems.Single(x => x.itemid == item.info.itemid).amount < 0)
{
item.amount += (int)dispenser.containedItems.Single(x => x.itemid == item.info.itemid).amount;
}
}
catch { }
}
private void OnDispenserBonus(ResourceDispenser dispenser, BaseEntity entity, Item item)
{
OnDispenserGather(dispenser, entity, item);
}
private void OnGrowableGathered(GrowableEntity growable, Item item, BasePlayer player)
{
float modifier;
if ( GatherResourceModifiers.TryGetValue(item.info.displayName.english, out modifier) )
{
item.amount = (int)(item.amount * modifier);
}
else if ( GatherResourceModifiers.TryGetValue("*", out modifier) )
{
item.amount = (int)(item.amount * modifier);
}
}
private void OnQuarryGather(MiningQuarry quarry, Item item)
{
float modifier;
if (QuarryResourceModifiers.TryGetValue(item.info.displayName.english, out modifier))
{
item.amount = (int)(item.amount * modifier);
}
else if (QuarryResourceModifiers.TryGetValue("*", out modifier))
{
item.amount = (int)(item.amount * modifier);
}
}
private void OnExcavatorGather(ExcavatorArm excavator, Item item)
{
float modifier;
if (ExcavatorResourceModifiers.TryGetValue(item.info.displayName.english, out modifier))
{
item.amount = (int)(item.amount * modifier);
}
else if (ExcavatorResourceModifiers.TryGetValue("*", out modifier))
{
item.amount = (int)(item.amount * modifier);
}
}
private void OnCollectiblePickup(Item item, BasePlayer player)
{
float modifier;
if (PickupResourceModifiers.TryGetValue(item.info.displayName.english, out modifier))
{
item.amount = (int)(item.amount * modifier);
}
else if (PickupResourceModifiers.TryGetValue("*", out modifier))
{
item.amount = (int)(item.amount * modifier);
}
}
private void OnSurveyGather(SurveyCharge surveyCharge, Item item)
{
float modifier;
if (SurveyResourceModifiers.TryGetValue(item.info.displayName.english, out modifier))
{
item.amount = (int)(item.amount * modifier);
}
else if (SurveyResourceModifiers.TryGetValue("*", out modifier))
{
item.amount = (int)(item.amount * modifier);
}
}
private void OnMiningQuarryEnabled(MiningQuarry quarry)
{
if (MiningQuarryResourceTickRate == DefaultMiningQuarryResourceTickRate) return;
quarry.CancelInvoke("ProcessResources");
quarry.InvokeRepeating("ProcessResources", MiningQuarryResourceTickRate, MiningQuarryResourceTickRate);
}
private void LoadConfigValues()
{
// Plugin settings
ChatPrefix = GetConfigValue("Settings", "ChatPrefix", DefaultChatPrefix);
ChatPrefixColor = GetConfigValue("Settings", "ChatPrefixColor", DefaultChatPrefixColor);
// Plugin options
var gatherResourceModifiers = GetConfigValue("Options", "GatherResourceModifiers", DefaultGatherResourceModifiers);
var gatherDispenserModifiers = GetConfigValue("Options", "GatherDispenserModifiers", DefaultGatherDispenserModifiers);
var quarryResourceModifiers = GetConfigValue("Options", "QuarryResourceModifiers", DefaultQuarryResourceModifiers);
var excavatorResourceModifiers = GetConfigValue("Options", "ExcavatorResourceModifiers", quarryResourceModifiers);
var pickupResourceModifiers = GetConfigValue("Options", "PickupResourceModifiers", DefaultPickupResourceModifiers);
var surveyResourceModifiers = GetConfigValue("Options", "SurveyResourceModifiers", DefaultSurveyResourceModifiers);
MiningQuarryResourceTickRate = GetConfigValue("Options", "MiningQuarryResourceTickRate", DefaultMiningQuarryResourceTickRate);
ExcavatorResourceTickRate = GetConfigValue("Options", "ExcavatorResourceTickRate", DefaultExcavatorResourceTickRate);
ExcavatorBeltSpeedMax = GetConfigValue("Options", "ExcavatorBeltSpeedMax", DefaultExcavatorBeltSpeedMax);
ExcavatorTimeForFullResources = GetConfigValue("Options", "ExcavatorTimeForFullResources", DefaultExcavatorTimeForFullResources);
GatherResourceModifiers = new Dictionary<string, float>();
foreach (var entry in gatherResourceModifiers)
{
float rate;
if (!float.TryParse(entry.Value.ToString(), out rate)) continue;
GatherResourceModifiers.Add(entry.Key, rate);
}
GatherDispenserModifiers = new Dictionary<string, float>();
foreach (var entry in gatherDispenserModifiers)
{
float rate;
if (!float.TryParse(entry.Value.ToString(), out rate)) continue;
GatherDispenserModifiers.Add(entry.Key, rate);
}
QuarryResourceModifiers = new Dictionary<string, float>();
foreach (var entry in quarryResourceModifiers)
{
float rate;
if (!float.TryParse(entry.Value.ToString(), out rate)) continue;
QuarryResourceModifiers.Add(entry.Key, rate);
}
ExcavatorResourceModifiers = new Dictionary<string, float>();
foreach (var entry in excavatorResourceModifiers)
{
float rate;
if (!float.TryParse(entry.Value.ToString(), out rate)) continue;
ExcavatorResourceModifiers.Add(entry.Key, rate);
}
PickupResourceModifiers = new Dictionary<string, float>();
foreach (var entry in pickupResourceModifiers)
{
float rate;
if (!float.TryParse(entry.Value.ToString(), out rate)) continue;
PickupResourceModifiers.Add(entry.Key, rate);
}
SurveyResourceModifiers = new Dictionary<string, float>();
foreach (var entry in surveyResourceModifiers)
{
float rate;
if (!float.TryParse(entry.Value.ToString(), out rate)) continue;
SurveyResourceModifiers.Add(entry.Key, rate);
}
// Plugin messages
NotAllowed = GetConfigValue("Messages", "NotAllowed", DefaultNotAllowed);
InvalidArgumentsGather = GetConfigValue("Messages", "InvalidArgumentsGather", DefaultInvalidArgumentsGather);
InvalidArgumentsDispenser = GetConfigValue("Messages", "InvalidArgumentsDispenserType", DefaultInvalidArgumentsDispenser);
InvalidArgumentsSpeed = GetConfigValue("Messages", "InvalidArgumentsMiningQuarrySpeed", DefaultInvalidArgumentsSpeed);
InvalidModifier = GetConfigValue("Messages", "InvalidModifier", DefaultInvalidModifier);
InvalidSpeed = GetConfigValue("Messages", "InvalidMiningQuarrySpeed", DefaultInvalidSpeed);
ModifyResource = GetConfigValue("Messages", "ModifyResource", DefaultModifyResource);
ModifyResourceRemove = GetConfigValue("Messages", "ModifyResourceRemove", DefaultModifyResourceRemove);
ModifySpeed = GetConfigValue("Messages", "ModifyMiningQuarrySpeed", DefaultModifySpeed);
InvalidResource = GetConfigValue("Messages", "InvalidResource", DefaultInvalidResource);
ModifyDispenser = GetConfigValue("Messages", "ModifyDispenser", DefaultModifyDispenser);
InvalidDispenser = GetConfigValue("Messages", "InvalidDispenser", DefaultInvalidDispenser);
HelpText = GetConfigValue("Messages", "HelpText", DefaultHelpText);
HelpTextAdmin = GetConfigValue("Messages", "HelpTextAdmin", DefaultHelpTextAdmin);
HelpTextPlayer = GetConfigValue("Messages", "HelpTextPlayer", DefaultHelpTextPlayer);
HelpTextPlayerGains = GetConfigValue("Messages", "HelpTextPlayerGains", DefaultHelpTextPlayerGains);
HelpTextPlayerDefault = GetConfigValue("Messages", "HelpTextPlayerDefault", DefaultHelpTextPlayerDefault);
HelpTextPlayerMiningQuarrySpeed = GetConfigValue("Messages", "HelpTextMiningQuarrySpeed", DefaultHelpTextPlayerMiningQuarrySpeed);
Dispensers = GetConfigValue("Messages", "Dispensers", DefaultDispensers);
Quarries = GetConfigValue("Messages", "MiningQuarries", DefaultQuarries);
Excavators = GetConfigValue("Messages", "Excavators", DefaultExcavators);
Charges = GetConfigValue("Messages", "SurveyCharges", DefaultCharges);
Pickups = GetConfigValue("Messages", "Pickups", DefaultPickups);
if (!configChanged) return;
PrintWarning("Configuration file updated.");
SaveConfig();
}
private T GetConfigValue<T>(string category, string setting, T defaultValue)
{
var data = Config[category] as Dictionary<string, object>;
object value;
if (data == null)
{
data = new Dictionary<string, object>();
Config[category] = data;
configChanged = true;
}
if (data.TryGetValue(setting, out value)) return (T)Convert.ChangeType(value, typeof(T));
value = defaultValue;
data[setting] = value;
configChanged = true;
return (T)Convert.ChangeType(value, typeof(T));
}
private void SetConfigValue<T>(string category, string setting, T newValue)
{
var data = Config[category] as Dictionary<string, object>;
object value;
if (data != null && data.TryGetValue(setting, out value))
{
value = newValue;
data[setting] = value;
configChanged = true;
}
SaveConfig();
}
private void SendMessage(BasePlayer player, string message, params object[] args) => player?.SendConsoleCommand("chat.add", 0, -1, string.Format($"<color={ChatPrefixColor}>{ChatPrefix}</color>: {message}", args), 1.0);
}
}

1282
plugins/ImageLibrary.cs Normal file

File diff suppressed because it is too large Load Diff

422
plugins/InventoryViewer.cs Normal file
View File

@ -0,0 +1,422 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Inventory Viewer", "Mughisi", "3.0.3", ResourceId = 871)]
[Description("Allows players with permission assigned to view anyone's inventory")]
public class InventoryViewer : RustPlugin
{
private readonly string RequiredPermission = "inventoryviewer.allowed";
private readonly Dictionary<BasePlayer, List<BasePlayer>> matches = new Dictionary<BasePlayer, List<BasePlayer>>();
/// <summary>
/// UnityEngine script to be attached to the player viewing someone's inventory.
/// </summary>
private class Inspector : MonoBehaviour
{
/// <summary>
/// The player doing the inspecting.
/// </summary>
private BasePlayer player;
/// <summary>
/// The player being inspected.
/// </summary>
private BasePlayer target;
/// <summary>
/// The tick counter used by the Inspector.
/// </summary>
private int ticks;
/// <summary>
/// Instantiates the Inspector script.
/// </summary>
public void Instantiate(BasePlayer player, BasePlayer target)
{
this.player = player;
this.target = target;
BeginLooting();
InvokeRepeating("UpdateLoot", 0f, 0.1f);
}
/// <summary>
/// Updates the loot.
/// </summary>
private void UpdateLoot()
{
if (!target)
{
return;
}
if (!target.inventory)
{
return;
}
ticks++;
if (!player.inventory.loot.IsLooting())
{
BeginLooting();
}
player.inventory.loot.SendImmediate();
player.SendNetworkUpdateImmediate();
}
/// <summary>
/// Stops inspecting.
/// </summary>
private void StopInspecting(bool forced = false)
{
if (ticks < 5 && !forced)
{
return;
}
CancelInvoke("UpdateLoot");
EndLooting();
}
/// <summary>
/// Starts the looting.
/// </summary>
private void BeginLooting()
{
player.inventory.loot.Clear();
if (!target)
{
return;
}
if (!target.inventory)
{
return;
}
player.inventory.loot.AddContainer(target.inventory.containerMain);
player.inventory.loot.AddContainer(target.inventory.containerWear);
player.inventory.loot.AddContainer(target.inventory.containerBelt);
player.inventory.loot.PositionChecks = false;
player.inventory.loot.entitySource = target;
player.inventory.loot.itemSource = null;
player.inventory.loot.MarkDirty();
player.inventory.loot.SendImmediate();
player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", "player_corpse");
player.SendNetworkUpdateImmediate();
}
/// <summary>
/// Ends the looting.
/// </summary>
private void EndLooting()
{
player.inventory.loot.MarkDirty();
if (player.inventory.loot.entitySource)
{
player.inventory.loot.entitySource.SendMessage("PlayerStoppedLooting", player, SendMessageOptions.DontRequireReceiver);
}
foreach (ItemContainer container in player.inventory.loot.containers)
{
if (container != null)
{
container.onDirty -= player.inventory.loot.MarkDirty;
}
}
player.inventory.loot.containers.Clear();
player.inventory.loot.entitySource = null;
player.inventory.loot.itemSource = null;
}
/// <summary>
/// Destroys the script
/// </summary>
public void Remove(bool forced = false)
{
if (ticks < 5 && !forced)
{
return;
}
StopInspecting(forced);
Destroy(this);
}
}
/// <summary>
/// Oxide hook that is triggered when the plugin is loaded.
/// </summary>
private void Loaded()
{
permission.RegisterPermission(RequiredPermission, this);
}
/// <summary>
/// Oxide hook that is triggered after the plugin is loaded to setup localized messages.
/// </summary>
private new void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
{ "InvalidArguments", "Invalid argument(s) supplied! Use '/{0} <name>' or '/{0} list <number>'." },
{ "InvalidSelection", "Invalid number, use the number in front of the player's name. Use '/{0} list' to check the list of players again." },
{ "MultiplePlayersFound", "Multiple players found with that name, please select one of these players by using '/{0} list <number>':" },
{ "NoListAvailable", "You do not have a players list available, use '/{0} <name>' instead." },
{ "NoPlayersFound", "Couldn't find any players matching that name." },
{ "NotAllowed", "You are not allowed to use this command." },
{ "TooManyPlayersFound", "Too many players were found, the list of matches is only showing the first 5. Try to be more specific." }
}, this);
}
/// <summary>
/// Oxide hook that is triggered when the plugin is unloaded.
/// </summary>
private void Unload()
{
Inspector[] inspectors = UnityEngine.Object.FindObjectsOfType<Inspector>();
foreach (Inspector inspector in inspectors)
inspector.Remove();
}
/// <summary>
/// Oxide hook that is triggered when a console command is executed.
/// </summary>
private void OnServerCommand(ConsoleSystem.Arg arg)
{
if (arg.cmd.FullName == "inventory.endloot")
{
BasePlayer player = arg.Player();
player.GetComponent<Inspector>()?.Remove();
}
}
/// <summary>
/// Oxide hook that is triggered when a player attempts to loot another player
/// </summary>
private object CanLootPlayer(BasePlayer target, BasePlayer looter)
{
if (looter.GetComponent<Inspector>() == null)
{
return null;
}
return true;
}
/// <summary>
/// Handles the /inspect command
/// </summary>
[ChatCommand("inspect")]
private void InspectCommand(BasePlayer player, string command, string[] args)
{
ViewInventoryCommand(player, command, args);
}
/// <summary>
/// Handles the /viewinv command
/// </summary>
[ChatCommand("viewinv")]
private void ViewInvCommand(BasePlayer player, string command, string[] args)
{
ViewInventoryCommand(player, command, args);
}
/// <summary>
/// Handles the /viewinventory command
/// </summary>
[ChatCommand("viewinventory")]
private void ViewInventoryCommand(BasePlayer player, string command, string[] args)
{
if (!CanUseCommand(player))
{
SendChatMessage(player, "NotAllowed");
return;
}
if (args.Length < 1)
{
SendChatMessage(player, "InvalidArguments", command);
return;
}
if (args[0] == "list")
{
if (args.Length == 1)
{
if (!matches.ContainsKey(player) || matches[player] == null)
{
SendChatMessage(player, "NoListAvailable", command);
return;
}
ShowMatches(player);
return;
}
int num;
if (int.TryParse(args[1], out num))
{
if (!matches.ContainsKey(player) || matches[player] == null)
{
SendChatMessage(player, "NoListAvailable", command);
return;
}
if (num > matches[player].Count)
{
SendChatMessage(player, "InvalidSelection", command);
ShowMatches(player);
return;
}
StartInspecting(player, matches[player][num - 1]);
return;
}
SendChatMessage(player, "InvalidArguments", command);
}
else
{
string name = string.Join(" ", args);
List<BasePlayer> players = FindPlayersByNameOrId(name);
switch (players.Count)
{
case 0:
SendChatMessage(player, "NoPlayersFound", command);
break;
case 1:
StartInspecting(player, players[0]);
break;
default:
SendChatMessage(player, "MultiplePlayersFound", command);
if (!matches.ContainsKey(player))
{
matches.Add(player, players);
}
else
{
matches[player] = players;
}
ShowMatches(player);
break;
}
}
}
/// <summary>
/// Looks up all players (active and sleeping) by a given (partial) name or steam id.
/// </summary>
private List<BasePlayer> FindPlayersByNameOrId(string nameOrId)
{
List<BasePlayer> matches = new List<BasePlayer>();
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
if (!string.IsNullOrEmpty(player.displayName))
{
if (player.displayName.ToLower().Contains(nameOrId.ToLower()))
{
matches.Add(player);
}
}
if (player.UserIDString == nameOrId)
{
matches.Add(player);
}
}
foreach (BasePlayer player in BasePlayer.sleepingPlayerList)
{
if (!string.IsNullOrEmpty(player.displayName))
{
if (player.displayName.ToLower().Contains(nameOrId.ToLower()))
{
matches.Add(player);
}
}
if (player.UserIDString == nameOrId)
{
matches.Add(player);
}
}
return matches.OrderBy(p => p.displayName).ToList();
}
/// <summary>
/// Shows the cached matches for the player.
/// </summary>
private void ShowMatches(BasePlayer player)
{
for (int i = 0; i < matches[player].Count; i++)
{
SendChatMessage(player, $"{i + 1}. {matches[player][i].displayName}");
if (i == 4 && i < matches[player].Count)
{
SendChatMessage(player, "TooManyPlayersFound");
break;
}
}
}
/// <summary>
/// Initializes the inspector for the given player and target.
/// </summary>
private void StartInspecting(BasePlayer player, BasePlayer target)
{
Inspector inspector = player.gameObject.GetComponent<Inspector>();
inspector?.Remove();
inspector = player.gameObject.AddComponent<Inspector>();
inspector.Instantiate(player, target);
}
/// <summary>
/// Checks if the specified BasePlayer has the required permission.
/// </summary>
private bool CanUseCommand(BasePlayer player)
{
return permission.UserHasPermission(player.UserIDString, RequiredPermission);
}
/// <summary>
/// Sends a localized chat message using the key to the specified player
/// </summary>
private void SendChatMessage(BasePlayer player, string key, params string[] args)
{
if (args == null || args.Length == 0)
{
Player.Reply(player, lang.GetMessage(key, this, player.UserIDString));
}
else
{
Player.Reply(player, string.Format(lang.GetMessage(key, this, player.UserIDString), args));
}
}
}
}

1979
plugins/Kits.cs Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,875 @@
using System;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
//Fixed next/previous/back navigation memory.
//now handles group names with spaces
namespace Oxide.Plugins
{
[Info("PermissionsManager", "Steenamaroo", "2.0.4", ResourceId = 0)]
class PermissionsManager : RustPlugin
{
#region Declarations
List<string> PlugList = new List<string>();
Dictionary<int, string> numberedPerms = new Dictionary<int, string>();
List<ulong> MenuOpen = new List<ulong>();
bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
const string permAllowed = "permissionsmanager.allowed";
Dictionary<ulong, Info> ActiveAdmins = new Dictionary<ulong, Info>();
public class Info
{
public string inheritedcheck = "";
public int noOfPlugs;
public int pluginPage = 1;
public int PPage = 1;
public int GPage = 1;
public string subjectGroup;
public BasePlayer subject;
}
string ButtonColour1 = "0.7 0.32 0.17 1";
string ButtonColour2 = "0.2 0.2 0.2 1";
#endregion
#region Hooks
void OnPluginLoaded(Plugin plugin)
{
if (plugin is PermissionsManager)
return;
Wipe();
OnServerInitialized();
}
void OnPluginUnloaded(Plugin plugin)
{
if (plugin is PermissionsManager)
return;
Wipe();
OnServerInitialized();
}
void Loaded()
{
lang.RegisterMessages(messages, this);
permission.RegisterPermission(permAllowed, this);
}
void OnServerInitialized()
{
foreach (BasePlayer player in BasePlayer.activePlayerList.Where(player => MenuOpen.Contains(player.userID)))
DestroyMenu(player, true);
if (!LoadConfigVariables())
{
Puts("Config file issue detected. Please delete file, or check syntax and fix.");
return;
}
SaveConfig();
}
void Unload()
{
foreach (BasePlayer player in BasePlayer.activePlayerList.Where(player => MenuOpen.Contains(player.userID)))
DestroyMenu(player, true);
}
void OnPlayerDisconnected(BasePlayer player)
{
if (MenuOpen.Contains(player.userID))
DestroyMenu(player, true);
}
void OnPlayerDeath(BasePlayer player, HitInfo info)
{
if (MenuOpen.Contains(player.userID))
DestroyMenu(player, true);
}
#endregion
#region Methods
void DestroyMenu(BasePlayer player, bool all)
{
CuiHelper.DestroyUi(player, "PMMainUI");
CuiHelper.DestroyUi(player, "PMPermsUI");
CuiHelper.DestroyUi(player, "PMConfirmUI");
if (all)
{
CuiHelper.DestroyUi(player, "PMBgUI");
MenuOpen.Remove(player.userID);
}
}
void Wipe()
{
PlugList.Clear();
numberedPerms.Clear();
}
void GetPlugs(BasePlayer player)
{
var path = ActiveAdmins[player.userID];
PlugList.Clear();
path.noOfPlugs = 0;
foreach (var entry in plugins.GetAll())
{
if (entry.IsCorePlugin)
continue;
var str = entry.ToString();
var charsToRemove = new string[] { "Oxide.Plugins." };
foreach (var c in charsToRemove)
str = str.Replace(c, string.Empty).ToLower();
foreach (var perm in permission.GetPermissions().ToList().Where(perm => perm.Contains($"{str}") && !(config.BlockList.Split(',').ToList().Contains($"{str}"))))
if (!PlugList.Contains(str))
PlugList.Add(str);
}
PlugList.Sort();
}
bool IsAuth(BasePlayer player) => player?.net?.connection != null && player.net.connection.authLevel == 2;
void SetButtons(bool on)
{
ButtonColour1 = (on) ? config.OffColour : config.OnColour;
ButtonColour2 = (on) ? config.OnColour : config.OffColour;
}
object[] PermsCheck(BasePlayer player, string group, string info)
{
bool has = false;
List<string> inherited = new List<string>();
var path = ActiveAdmins[player.userID];
if (group == "true")
{
if (permission.GroupHasPermission(path.subjectGroup, info))
has = true;
}
else
{
UserData userData = permission.GetUserData(path.subject.UserIDString);
if (userData.Perms.Contains(info))
has = true;
foreach (var group1 in permission.GetUserGroups(path.subject.UserIDString))
if (permission.GroupHasPermission(group1, info))
inherited.Add(group1);
}
return new object[] { has, inherited };
}
#endregion
#region UI
void PMBgUI(BasePlayer player)
{
MenuOpen.Add(player.userID);
string guiString = String.Format("0.1 0.1 0.1 {0}", config.guitransparency);
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel { Image = { Color = guiString }, RectTransform = { AnchorMin = "0.3 0.1", AnchorMax = "0.7 0.9" }, CursorEnabled = true, FadeOut = 0.1f }, "Overlay", "PMBgUI");
elements.Add(new CuiButton { Button = { Color = "0 0 0 1" }, RectTransform = { AnchorMin = $"0 0.95", AnchorMax = $"0.998 1" }, Text = { Text = String.Empty } }, mainName);
elements.Add(new CuiButton { Button = { Color = "0 0 0 1" }, RectTransform = { AnchorMin = $"0 0", AnchorMax = $"0.998 0.05" }, Text = { Text = String.Empty } }, mainName);
elements.Add(new CuiButton { Button = { Command = "ClosePM", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.955 0.96", AnchorMax = "0.99 0.995" }, Text = { Text = "X", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
CuiHelper.AddUi(player, elements);
}
void PMMainUI(BasePlayer player, bool group, int page)
{
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel { Image = { Color = "0 0 0 0" }, RectTransform = { AnchorMin = "0.32 0.1", AnchorMax = "0.68 0.9" }, CursorEnabled = true }, "Overlay", "PMMainUI");
elements.Add(new CuiElement { Parent = "PMMainUI", Components = { new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" } } });
string subject = (group) ? lang.GetMessage("GUIPlayers", this) : lang.GetMessage("GUIGroups", this);
string current = (!group) ? lang.GetMessage("GUIPlayers", this) : lang.GetMessage("GUIGroups", this);
elements.Add(new CuiLabel { Text = { Text = "Permissions Manager V2", FontSize = 16, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.95", AnchorMax = "1 1" } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"PMTogglePlayerGroup {group} 1", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.4 0.02", AnchorMax = "0.6 0.04" }, Text = { Text = lang.GetMessage("All", this) + " " + subject, FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
int pos1 = 20 - (page * 20), quantity = 0;
float top = 0.87f;
float bottom = 0.85f;
elements.Add(new CuiLabel { Text = { Text = lang.GetMessage("All", this) + " " + current, FontSize = 14, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.9", AnchorMax = "1 0.97" } }, mainName);
if (group)
foreach (var grp in permission.GetGroups())
{
pos1++;
quantity++;
if (pos1 > 0 && pos1 < 21)
{
elements.Add(new CuiButton { Button = { Command = $"PMSelected group {grp}", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.3 {bottom}", AnchorMax = $"0.7 {top}" }, Text = { Text = $"{grp}", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
top = top - 0.025f;
bottom = bottom - 0.025f;
}
}
else
foreach (var plyr in GetAllPlayers())
{
pos1++;
quantity++;
if (pos1 > 0 && pos1 < 21)
{
elements.Add(new CuiButton { Button = { Command = $"PMSelected player {plyr.userID}", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.3 {bottom}", AnchorMax = $"0.7 {top}" }, Text = { Text = $"{plyr.displayName}", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
top = top - 0.025f;
bottom = bottom - 0.025f;
}
}
if (quantity > (page * 20))
elements.Add(new CuiButton { Button = { Command = $"PMTogglePlayerGroup {!group} {page + 1}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.8 0.02", AnchorMax = "0.9 0.04" }, Text = { Text = lang.GetMessage("->", this), FontSize = 11, Align = TextAnchor.MiddleCenter }, }, mainName);
if (page > 1)
elements.Add(new CuiButton { Button = { Command = $"PMTogglePlayerGroup {!group} {page - 1}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.1 0.02", AnchorMax = "0.2 0.04" }, Text = { Text = lang.GetMessage("<-", this), FontSize = 11, Align = TextAnchor.MiddleCenter }, }, mainName);
CuiHelper.AddUi(player, elements);
}
void PlugsUI(BasePlayer player, string msg, string group, int page)
{
var path = ActiveAdmins[player.userID];
var backpage = group == "false" ? path.PPage : path.GPage;
string toggle = (group == "true") ? "false" : "true";
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel { Image = { Color = "0 0 0 0" }, RectTransform = { AnchorMin = "0.32 0.1", AnchorMax = "0.68 0.9" }, CursorEnabled = true }, "Overlay", "PMPermsUI");
elements.Add(new CuiElement { Parent = "PMPermsUI", Components = { new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" } } });
int plugsTotal = 0, pos1 = 60 - (page * 60), next = page + 1, previous = page - 1;
for (int i = 0; i < PlugList.Count; i++)
{
pos1++;
plugsTotal++;
if (pos1 > 0 && pos1 < 21)
elements.Add(new CuiButton { Button = { Command = $"PermsList {i} null null {group} null 1", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.1 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.3 {0.91 - (pos1 * 3f) / 100f}" }, Text = { Text = $"{PlugList[i]}", FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
if (pos1 > 20 && pos1 < 41)
elements.Add(new CuiButton { Button = { Command = $"PermsList {i} null null {group} null 1", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.4 {(0.89 - ((pos1 - 20) * 3f) / 100f)}", AnchorMax = $"0.6 {0.91 - ((pos1 - 20) * 3f) / 100f}" }, Text = { Text = $"{PlugList[i]}", FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
if (pos1 > 40 && pos1 < 61)
elements.Add(new CuiButton { Button = { Command = $"PermsList {i} null null {group} null 1", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.7 {(0.89 - ((pos1 - 40) * 3f) / 100f)}", AnchorMax = $"0.9 {0.91 - ((pos1 - 40) * 3f) / 100f}" }, Text = { Text = $"{PlugList[i]}", FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
}
elements.Add(new CuiButton { Button = { Command = $"PMTogglePlayerGroup {toggle} {backpage}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.55 0.02", AnchorMax = "0.75 0.04" }, Text = { Text = lang.GetMessage("GUIBack", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiLabel { Text = { Text = msg, FontSize = 16, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.95", AnchorMax = "1 1" } }, mainName);
if (group == "false")
elements.Add(new CuiButton { Button = { Command = "Groups 1", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.25 0.02", AnchorMax = "0.45 0.04" }, Text = { Text = lang.GetMessage("GUIGroups", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
else
elements.Add(new CuiButton { Button = { Command = "PlayersIn 1", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.25 0.02", AnchorMax = "0.45 0.04" }, Text = { Text = lang.GetMessage("GUIPlayers", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
if (plugsTotal > (page * 60))
elements.Add(new CuiButton { Button = { Command = $"Navigate {group} {next}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.8 0.02", AnchorMax = "0.9 0.04" }, Text = { Text = lang.GetMessage("->", this), FontSize = 11, Align = TextAnchor.MiddleCenter }, }, mainName);
if (page > 1)
elements.Add(new CuiButton { Button = { Command = $"Navigate {group} {previous}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.1 0.02", AnchorMax = "0.2 0.04" }, Text = { Text = lang.GetMessage("<-", this), FontSize = 11, Align = TextAnchor.MiddleCenter }, }, mainName);
CuiHelper.AddUi(player, elements);
}
void PMPermsUI(BasePlayer player, string msg, int PlugNumber, string group, int page)
{
var path = ActiveAdmins[player.userID];
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel { Image = { Color = "0 0 0 0" }, RectTransform = { AnchorMin = "0.32 0.1", AnchorMax = "0.68 0.9" }, CursorEnabled = true }, "Overlay", "PMPermsUI");
elements.Add(new CuiElement { Parent = "PMPermsUI", Components = { new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" } } });
int permsTotal = 0, pos1 = 20 - (page * 20), next = (page + 1), previous = (page - 1);
elements.Add(new CuiButton { Button = { Command = $"PermsList {PlugNumber} grant null {group} all {page}", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.5 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.6 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUIAll", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"PermsList {PlugNumber} revoke null {group} all {page}", Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.65 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.75 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUINone", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
var elements1 = new CuiElementContainer();
bool list = false;
foreach (var perm in numberedPerms)
{
SetButtons(true);
pos1++;
permsTotal++;
var permNo = perm.Key;
string showName = numberedPerms[permNo];
string output = showName.Substring(showName.IndexOf('.') + 1);
string granted = lang.GetMessage("GUIGranted", this);
if (pos1 > 0 && pos1 < 21)
{
granted = lang.GetMessage("GUIGranted", this);
if ((bool)PermsCheck(player, group, numberedPerms[permNo])[0])
SetButtons(false);
List<string> inheritcheck = (List<string>)(PermsCheck(player, group, numberedPerms[permNo])[1]);
if (inheritcheck.Count > 0)
{
if (path.inheritedcheck == numberedPerms[permNo])
{
var mainName1 = elements1.Add(new CuiPanel { Image = { Color = "0.1 0.1 0.1 0.99" }, RectTransform = { AnchorMin = "0.3 0.1", AnchorMax = "0.7 0.86" }, CursorEnabled = true, FadeOut = 0.1f }, "Overlay", "PMConfirmUI");
elements1.Add(new CuiButton { Button = { Command = $"ShowInherited {PlugNumber} null {numberedPerms[permNo]} {group} null {page} -", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.4 0.01", AnchorMax = "0.6 0.05" }, Text = { Text = lang.GetMessage("GUIBack", this), FontSize = 14, Align = TextAnchor.MiddleCenter }, }, mainName1);
float h1 = 0, h2 = 0;
elements1.Add(new CuiButton { Button = { Command = "", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.3 0.8", AnchorMax = "0.7 0.825" }, Text = { Text = $"{numberedPerms[permNo]}", FontSize = 12, Align = TextAnchor.MiddleCenter }, }, mainName1);
elements1.Add(new CuiLabel { Text = { Text = $"{lang.GetMessage("GUIInheritedFrom", this)}", FontSize = 11, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.77", AnchorMax = "1 0.8" } }, mainName1);
for (int i = 0; i < inheritcheck.Count; i++)
{
h1 = i * 0.022f;
h2 = i * 0.022f;
elements1.Add(new CuiLabel { Text = { Text = $"{inheritcheck[i]}", FontSize = 11, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = $"0 {0.7 - h1}", AnchorMax = $"1 {0.75 - h2}" } }, mainName1);
}
list = true;
}
elements.Add(new CuiButton { Button = { Command = $"ShowInherited {PlugNumber} null {numberedPerms[permNo]} {group} null {page} {numberedPerms[permNo]}", Color = config.InheritedColour }, RectTransform = { AnchorMin = $"0.8 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.9 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUIInherited", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
}
elements.Add(new CuiButton { Button = { Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.1 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.45 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = $"{output}", FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"PermsList {PlugNumber} grant {numberedPerms[permNo]} {group} null {page}", Color = ButtonColour1 }, RectTransform = { AnchorMin = $"0.5 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.6 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUIGranted", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"PermsList {PlugNumber} revoke {numberedPerms[permNo]} {group} null {page}", Color = ButtonColour2 }, RectTransform = { AnchorMin = $"0.65 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.75 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUIRevoked", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
}
}
elements.Add(new CuiButton { Button = { Command = $"Navigate {group} {path.pluginPage}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.4 0.02", AnchorMax = "0.6 0.04" }, Text = { Text = lang.GetMessage("GUIBack", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiLabel { Text = { Text = msg, FontSize = 16, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.95", AnchorMax = "1 1" } }, mainName);
if (permsTotal > (page * 20))
elements.Add(new CuiButton { Button = { Command = $"PermsList {PlugNumber} null null {group} null {next}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.8 0.02", AnchorMax = "0.9 0.04" }, Text = { Text = "->", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
if (page > 1)
elements.Add(new CuiButton { Button = { Command = $"PermsList {PlugNumber} null null {group} null {previous}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.1 0.02", AnchorMax = "0.2 0.04" }, Text = { Text = "<-", FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
CuiHelper.AddUi(player, elements);
if (list)
CuiHelper.AddUi(player, elements1);
}
void ViewPlayersUI(BasePlayer player, string msg, int page)
{
var path = ActiveAdmins[player.userID];
var outmsg = string.Format(lang.GetMessage("GUIPlayersIn", this), msg);
string guiString = String.Format("0.1 0.1 0.1 {0}", config.guitransparency);
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel { Image = { Color = "0 0 0 0" }, RectTransform = { AnchorMin = "0.32 0.1", AnchorMax = "0.68 0.9" }, CursorEnabled = true }, "Overlay", "PMPermsUI");
elements.Add(new CuiElement { Parent = "PMPermsUI", Components = { new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" } } });
int playerCounter = 0, pos1 = 20 - (page * 20), next = page + 1, previous = page - 1;
foreach (var useringroup in permission.GetUsersInGroup(path.subjectGroup))
{
pos1++;
playerCounter++;
if (pos1 > 0 && pos1 < 21)
elements.Add(new CuiButton { Button = { Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.2 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.8 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = $"{useringroup}", FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
}
elements.Add(new CuiLabel { Text = { Text = outmsg, FontSize = 16, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.95", AnchorMax = "1 1" } }, mainName);
if (playerCounter > (page * 20))
elements.Add(new CuiButton { Button = { Command = $"PlayersIn {next}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.8 0.02", AnchorMax = "0.9 0.04" }, Text = { Text = lang.GetMessage("->", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
if (page > 1)
elements.Add(new CuiButton { Button = { Command = $"PlayersIn {previous}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.1 0.02", AnchorMax = "0.2 0.04" }, Text = { Text = lang.GetMessage("<-", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"PMEmptyGroup", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.25 0.02", AnchorMax = "0.45 0.04" }, Text = { Text = lang.GetMessage("removePlayers", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"Navigate true {path.PPage}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.55 0.02", AnchorMax = "0.75 0.04" }, Text = { Text = lang.GetMessage("GUIBack", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
CuiHelper.AddUi(player, elements);
}
void ViewGroupsUI(BasePlayer player, string msg, int page)
{
var path = ActiveAdmins[player.userID];
var outmsg = string.Format(lang.GetMessage("GUIGroupsFor", this), msg);
string guiString = String.Format("0.1 0.1 0.1 {0}", config.guitransparency);
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel { Image = { Color = "0 0 0 0" }, RectTransform = { AnchorMin = "0.32 0.1", AnchorMax = "0.68 0.9" }, CursorEnabled = true }, "Overlay", "PMPermsUI");
elements.Add(new CuiElement { Parent = "PMPermsUI", Components = { new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" } } });
int groupTotal = 0, pos1 = 20 - (page * 20), next = page + 1, previous = page - 1;
foreach (var group in permission.GetGroups())
{
SetButtons(true);
pos1++;
groupTotal++;
if (pos1 > 0 && pos1 < 21)
{
foreach (var user in permission.GetUsersInGroup(group))
{
if (user.Contains(path.subject.UserIDString))
{
SetButtons(false);
break;
}
}
//MAKE THIS OPEN UI FOR THAT GROUP
elements.Add(new CuiButton { Button = { Color = config.ButtonColour }, RectTransform = { AnchorMin = $"0.2 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.5 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = $"{group}", FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"GroupAddRemove add {RemoveSpaces(group)} {page}", Color = ButtonColour1 }, RectTransform = { AnchorMin = $"0.55 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.65 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUIGranted", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiButton { Button = { Command = $"GroupAddRemove remove {RemoveSpaces(group)} {page}", Color = ButtonColour2 }, RectTransform = { AnchorMin = $"0.7 {(0.89 - (pos1 * 3f) / 100f)}", AnchorMax = $"0.8 {(0.91 - (pos1 * 3f) / 100f)}" }, Text = { Text = lang.GetMessage("GUIRevoked", this), FontSize = 10, Align = TextAnchor.MiddleCenter } }, mainName);
}
}
elements.Add(new CuiButton { Button = { Command = $"Navigate false {path.pluginPage}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.4 0.02", AnchorMax = "0.6 0.04" }, Text = { Text = lang.GetMessage("GUIBack", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
elements.Add(new CuiLabel { Text = { Text = outmsg, FontSize = 16, Align = TextAnchor.MiddleCenter }, RectTransform = { AnchorMin = "0 0.95", AnchorMax = "1 1" } }, mainName);
if (groupTotal > (page * 20))
elements.Add(new CuiButton { Button = { Command = $"Groups {next}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.7 0.02", AnchorMax = "0.8 0.04" }, Text = { Text = lang.GetMessage("->", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
if (page > 1)
elements.Add(new CuiButton { Button = { Command = $"Groups {previous}", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.2 0.02", AnchorMax = "0.3 0.04" }, Text = { Text = lang.GetMessage("<-", this), FontSize = 11, Align = TextAnchor.MiddleCenter } }, mainName);
CuiHelper.AddUi(player, elements);
}
#endregion
#region console commands
[ConsoleCommand("PMToMain")]
private void PMToMain(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
PMMainUI(player, false, 1);
}
[ConsoleCommand("PMTogglePlayerGroup")]
private void PMTogglePlayerGroup(ConsoleSystem.Arg arg, bool group, int page)
{
var player = arg?.Connection?.player as BasePlayer;
if (player == null || arg.Args == null || arg.Args.Length != 2) return;
group = !(Convert.ToBoolean(arg.Args[0]));
page = Convert.ToInt16(arg.Args[1]);
if (group)
ActiveAdmins[player.userID].GPage = page;
else
ActiveAdmins[player.userID].PPage = page;
DestroyMenu(player, false);
PMMainUI(player, group, page);
}
[ConsoleCommand("ShowInherited")]
private void ShowInherited(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
if (player == null || arg.Args == null || arg.Args.Length < 6) return;
int pageNo = Convert.ToInt32(arg.Args[5]);
path.inheritedcheck = arg.Args[6];
var plugNumber = Convert.ToInt32(arg.Args[0]);
string plugName = PlugList[Convert.ToInt32(arg.Args[0])];
DestroyMenu(player, false);
PMPermsUI(player, $"{path.subject.displayName} - {plugName}", plugNumber, "false", pageNo);
}
[ConsoleCommand("PMEmptyGroup")]
private void PMEmptyGroup(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var elements1 = new CuiElementContainer();
var mainName1 = elements1.Add(new CuiPanel { Image = { Color = "0.1 0.1 0.1 0.8" }, RectTransform = { AnchorMin = "0.4 0.42", AnchorMax = "0.6 0.48" }, CursorEnabled = true, FadeOut = 0.1f }, "Overlay", "PMConfirmUI");
elements1.Add(new CuiElement { Parent = "PMConfirmUI", Components = { new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" } } });
elements1.Add(new CuiButton { Button = { Command = $"Empty true", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.1 0.2", AnchorMax = "0.4 0.8" }, Text = { Text = lang.GetMessage("confirm", this), FontSize = 14, Align = TextAnchor.MiddleCenter }, }, mainName1);
elements1.Add(new CuiButton { Button = { Command = $"Empty false", Color = config.ButtonColour }, RectTransform = { AnchorMin = "0.6 0.2", AnchorMax = "0.9 0.8" }, Text = { Text = lang.GetMessage("cancel", this), FontSize = 14, Align = TextAnchor.MiddleCenter }, }, mainName1);
CuiHelper.AddUi(player, elements1);
}
[ConsoleCommand("EmptyGroup")]//user console command
private void EmptyGroup(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
if (player != null && !HasPermission(player.UserIDString, permAllowed) & !IsAuth(player))
{
SendReply(player, config.TitleColour + lang.GetMessage("title", this) + "</color>" + config.MessageColour + lang.GetMessage("NotAdmin", this) + "</color>");
return;
}
if (arg.Args == null || arg.Args.Length < 1)
return;
string groupname = arg.Args[0];
var list = permission.GetUsersInGroup(groupname);
if (list == null || list.Length == 0)
{
Puts($"Group {groupname} was not found.");
return;
}
foreach (var user in permission.GetUsersInGroup(groupname))
{
string str = user.Substring(0, 17);
permission.RemoveUserGroup(str, groupname);
}
Puts($"All users were removed from {groupname}");
}
[ConsoleCommand("Empty")]
private void Empty(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
string confirmation = arg.Args[0];
if (confirmation == "true")
{
int count = 0;
foreach (var user in permission.GetUsersInGroup(path.subjectGroup))
{
count++;
string str = user.Substring(0, 17);
permission.RemoveUserGroup(str, path.subjectGroup);
DestroyMenu(player, false);
var argsOut = new string[] { "group", path.subjectGroup };
CmdPerms(player, null, argsOut);
}
if (count == 0)
CuiHelper.DestroyUi(player, "PMConfirmUI");
}
else
CuiHelper.DestroyUi(player, "PMConfirmUI");
}
string RemoveSpaces(string input)=>input.Replace(" ", "-");
string RemoveDashes(string input)=>input.Replace("-", " ");
[ConsoleCommand("GroupAddRemove")]
private void GroupAddRemove(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
if (player == null || arg.Args == null || arg.Args.Length < 3) return;
string Pname = path.subject.userID.ToString();
string userGroup = RemoveDashes(arg.Args[1]);
int page = Convert.ToInt32(arg.Args[2]);
if (arg.Args[0] == "add")
permission.AddUserGroup(Pname, userGroup);
if (arg.Args[0] == "remove")
permission.RemoveUserGroup(Pname, userGroup);
DestroyMenu(player, false);
ViewGroupsUI(player, $"{path.subject.displayName}", page);
}
[ConsoleCommand("Groups")]
private void GroupsPM(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
if (player == null || arg.Args == null || arg.Args.Length < 1) return;
ActiveAdmins[player.userID].GPage = Convert.ToInt32(arg.Args[0]);
DestroyMenu(player, false);
ViewGroupsUI(player, $"{path.subject.displayName}", path.GPage);
}
[ConsoleCommand("PlayersIn")]
private void PlayersPM(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
if (player == null || arg.Args == null || arg.Args.Length < 1) return;
ActiveAdmins[player.userID].PPage = Convert.ToInt32(arg.Args[0]);
DestroyMenu(player, false);
ViewPlayersUI(player, $"{path.subjectGroup}", path.PPage);
}
[ConsoleCommand("ClosePM")]
private void ClosePM(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
if (player == null) return;
ActiveAdmins.Remove(player.userID);
DestroyMenu(player, true);
}
[ConsoleCommand("Navigate")]
private void Navigate(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
if (player == null || arg.Args == null || arg.Args.Length < 2) return;
ActiveAdmins[player.userID].pluginPage = Convert.ToInt32(arg.Args[1]);
DestroyMenu(player, false);
string[] argsOut;
if (arg.Args[0] == "true")
{
argsOut = new string[] { "group", path.subjectGroup, path.pluginPage.ToString() };
CmdPerms(player, null, argsOut);
}
else
{
argsOut = new string[] { "player", path.subject.userID.ToString(), path.pluginPage.ToString() };
CmdPerms(player, null, argsOut);
}
return;
}
[ConsoleCommand("PMSelected")]
private void PMSelected(ConsoleSystem.Arg arg)
{
var player = arg?.Connection?.player as BasePlayer;
DestroyMenu(player, false);
string[] argsOut;
argsOut = new string[] { arg.Args[0], arg.Args[1] };
if (arg.Args[0] == "player")
ActiveAdmins[player.userID].subject = FindPlayer(Convert.ToUInt64(arg.Args[1]));
else
ActiveAdmins[player.userID].subjectGroup = arg.Args[1];
CmdPerms(player, null, argsOut);
return;
}
[ConsoleCommand("PermsList")]
private void PermsList(ConsoleSystem.Arg arg, int plugNumber)
{
var player = arg?.Connection?.player as BasePlayer;
var path = ActiveAdmins[player.userID];
if (player == null || arg.Args == null || arg.Args.Length < 6) return;
int pageNo = Convert.ToInt32(arg.Args[5]);
string Pname;
string group = arg.Args[3];
if (arg.Args[4] == "all")
{
if (arg.Args[2] != null)
{
Pname = path.subject?.userID.ToString();
string action = arg.Args[1];
foreach (var perm in numberedPerms)
{
if (config.AllPerPage == true && perm.Key > (pageNo * 20) - 20 && perm.Key < ((pageNo * 20) + 1))
{
if (action == "grant" && group == "false")
permission.GrantUserPermission(Pname, perm.Value, null);
if (action == "revoke" && group == "false")
permission.RevokeUserPermission(Pname, perm.Value);
if (action == "grant" && group == "true")
permission.GrantGroupPermission(path.subjectGroup, perm.Value, null);
if (action == "revoke" && group == "true")
permission.RevokeGroupPermission(path.subjectGroup, perm.Value);
}
if (config.AllPerPage == false)
{
if (action == "grant" && group == "false")
permission.GrantUserPermission(Pname, perm.Value, null);
if (action == "revoke" && group == "false")
permission.RevokeUserPermission(Pname, perm.Value);
if (action == "grant" && group == "true")
permission.GrantGroupPermission(path.subjectGroup, perm.Value, null);
if (action == "revoke" && group == "true")
permission.RevokeGroupPermission(path.subjectGroup, perm.Value);
}
}
}
}
else
{
Pname = path.subject?.userID.ToString();
string action = arg.Args[1];
string PermInHand = arg.Args[2];
if (arg.Args[2] != null)
{
if (action == "grant" && group == "false")
permission.GrantUserPermission(Pname, PermInHand, null);
if (action == "revoke" && group == "false")
permission.RevokeUserPermission(Pname, PermInHand);
if (action == "grant" && group == "true")
permission.GrantGroupPermission(path.subjectGroup, PermInHand, null);
if (action == "revoke" && group == "true")
permission.RevokeGroupPermission(path.subjectGroup, PermInHand);
}
}
plugNumber = Convert.ToInt32(arg.Args[0]);
string plugName = PlugList[plugNumber];
numberedPerms.Clear();
int numOfPerms = 0;
foreach (var perm in permission.GetPermissions())
{
if (perm.Contains($"{plugName}."))
{
numOfPerms++;
numberedPerms.Add(numOfPerms, perm);
}
}
DestroyMenu(player, false);
if (group == "false")
PMPermsUI(player, $"{path.subject.displayName} - {plugName}", plugNumber, group, pageNo);
else
PMPermsUI(player, $"{path.subjectGroup} - {plugName}", plugNumber, group, pageNo);
return;
}
#endregion
#region chat commands
[ChatCommand("perms")]
void CmdPerms(BasePlayer player, string command, string[] args)
{
if (!HasPermission(player.UserIDString, permAllowed) & !IsAuth(player))
{
SendReply(player, config.TitleColour + lang.GetMessage("title", this) + "</color>" + config.MessageColour + lang.GetMessage("NotAdmin", this) + "</color>");
return;
}
if (!ActiveAdmins.ContainsKey(player.userID))
ActiveAdmins.Add(player.userID, new Info());
var path = ActiveAdmins[player.userID];
GetPlugs(player);
int page = 1;
if (args.Length == 3)
page = Convert.ToInt32(args[2]);
if (args == null || args.Length < 2)
{
bool group = (args != null && args.Length == 1 && args[0] == "group") ? true : false;
if (MenuOpen.Contains(player.userID))
DestroyMenu(player, group);
PMBgUI(player);
PMMainUI(player, group, 1);
return;
}
if (args[0] == "player")
{
UInt64 n = 0;
bool isNumeric = UInt64.TryParse(args[1], out n);
path.subject = isNumeric ? FindPlayer(n) : FindPlayerByName(args[1]);
if (path.subject == null)
{
SendReply(player, config.TitleColour + lang.GetMessage("title", this) + "</color>" + config.MessageColour + lang.GetMessage("NoPlayer", this) + "</color>", args[1]);
return;
}
string msg = string.Format(lang.GetMessage("GUIName", this), path.subject.displayName);
if (MenuOpen.Contains(player.userID))
DestroyMenu(player, true);
PMBgUI(player);
PlugsUI(player, msg, "false", page);
}
else if (args[0] == "group")
{
List<string> Groups = new List<string>();
foreach (var group in permission.GetGroups())
Groups.Add(group);
if (Groups.Contains($"{args[1]}"))
{
string msg = string.Format(lang.GetMessage("GUIName", this), args[1]);
ActiveAdmins[player.userID].subjectGroup = args[1];
if (MenuOpen.Contains(player.userID))
DestroyMenu(player, true);
PMBgUI(player);
PlugsUI(player, msg, "true", page);
return;
}
SendReply(player, config.TitleColour + lang.GetMessage("title", this) + "</color>" + config.MessageColour + lang.GetMessage("NoGroup", this) + "</color>", args[1]);
}
else
SendReply(player, config.TitleColour + lang.GetMessage("title", this) + "</color>" + config.MessageColour + lang.GetMessage("Syntax", this) + "</color>");
}
List<BasePlayer> GetAllPlayers()
{
List<BasePlayer> available = new List<BasePlayer>();
foreach (BasePlayer online in BasePlayer.activePlayerList)
available.Add(online);
foreach (BasePlayer sleeper in BasePlayer.sleepingPlayerList)
available.Add(sleeper);
return available;
}
BasePlayer FindPlayer(ulong ID)
{
BasePlayer result = null;
foreach (BasePlayer current in GetAllPlayers())
{
if (current.userID == ID)
result = current;
}
return result;
}
BasePlayer FindPlayerByName(string name)
{
BasePlayer result = null;
foreach (var player in GetAllPlayers())
{
if (player.displayName.Equals(name, StringComparison.OrdinalIgnoreCase)
|| player.UserIDString.Contains(name, CompareOptions.OrdinalIgnoreCase)
|| player.displayName.Contains(name, CompareOptions.OrdinalIgnoreCase))
result = player;
}
return result;
}
#endregion
#region config
public ConfigData config;
public class ConfigData
{
[JsonProperty(PropertyName = "Options - GUI Transparency 0-1")]
public double guitransparency = 0.9;
[JsonProperty(PropertyName = "Chat - Title colour")]
public string TitleColour = "<color=orange>";
[JsonProperty(PropertyName = "Chat - Message colour")]
public string MessageColour = "<color=white>";
[JsonProperty(PropertyName = "Options - Plugin BlockList")]
public string BlockList = "";
[JsonProperty(PropertyName = "GUI - Label colour")]
public string ButtonColour = "0.7 0.32 0.17 1";
[JsonProperty(PropertyName = "GUI - On colour")]
public string OnColour = "0.7 0.32 0.17 1";
[JsonProperty(PropertyName = "GUI - Off colour")]
public string OffColour = "0.2 0.2 0.2 1";
[JsonProperty(PropertyName = "GUI - All = per page")]
public bool AllPerPage = false;
[JsonProperty(PropertyName = "GUI - Inherited colour")]
public string InheritedColour = "0.9 0.6 0.17 1";
}
private bool LoadConfigVariables()
{
try
{
config = Config.ReadObject<ConfigData>();
}
catch
{
return false;
}
SaveConfig(config);
return true;
}
protected override void LoadDefaultConfig()
{
Puts("Creating new config file.");
var config = new ConfigData();
SaveConfig(config);
}
void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
#endregion
#region messages
readonly Dictionary<string, string> messages = new Dictionary<string, string>()
{
{"title", "Permissions Manager: " },
{"NoGroup", "Group {0} was not found." },
{"NoPlayer", "Player {0} was not found." },
{"GUIAll", "Grant All" },
{"GUINone", "Revoke All" },
{"GUIBack", "Back" },
{"GUIGroups", "Groups" },
{"GUIPlayers", "Players" },
{"GUIInherited", "Inherited" },
{"GUIInheritedFrom", "Inherited from" },
{"GUIGranted", "Granted" },
{"GUIRevoked", "Revoked" },
{"GUIName", "Permissions for {0}" },
{"GUIGroupsFor", "Groups for {0}"},
{"GUIPlayersIn", "Players in {0}"},
{"removePlayers", "Remove All Players"},
{"confirm", "Confirm"},
{"cancel", "Cancel"},
{"NotAdmin", "You need Auth Level 2, or permission, to use this command."},
{"Back", "Back"},
{"All", "All"},
{"Syntax", "Use /perms, /perms player *name*, or /perms group *name*"}
};
#endregion
}
}

File diff suppressed because it is too large Load Diff

519
plugins/QuickSmelt.cs Normal file
View File

@ -0,0 +1,519 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Quick Smelt", "Iv Misticos", "5.1.3")]
[Description("Increases the speed of the furnace smelting")]
class QuickSmelt : RustPlugin
{
#region Variables
private static QuickSmelt _instance;
private const string PermissionUse = "quicksmelt.use";
#endregion
#region Configuration
private static Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Use Permission")]
public bool UsePermission = true;
[JsonProperty(PropertyName = "Speed Multipliers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> SpeedMultipliers = new Dictionary<string, float>
{
{"global", 1.0f},
{"furnace.shortname", 1.0f}
};
[JsonProperty(PropertyName = "Fuel Usage Speed Multipliers",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, float> FuelSpeedMultipliers = new Dictionary<string, float>
{
{"global", 1.0f},
{"furnace.shortname", 1.0f}
};
[JsonProperty(PropertyName = "Fuel Usage Multipliers",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> FuelUsageMultipliers = new Dictionary<string, int>
{
{"global", 1},
{"furnace.shortname", 1}
};
[JsonProperty(PropertyName = "Output Multipliers", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, Dictionary<string, float>> OutputMultipliers =
new Dictionary<string, Dictionary<string, float>>
{
{
"global", new Dictionary<string, float>
{
{"global", 1.0f}
}
},
{
"furnace.shortname", new Dictionary<string, float>
{
{"item.shortname", 1.0f}
}
}
};
[JsonProperty(PropertyName = "Whitelist", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, List<string>> Whitelist = new Dictionary<string, List<string>>
{
{
"global", new List<string>
{
"item.shortname"
}
},
{
"furnace.shortname", new List<string>
{
"item.shortname"
}
}
};
[JsonProperty(PropertyName = "Blacklist", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, List<string>> Blacklist = new Dictionary<string, List<string>>
{
{
"global", new List<string>
{
"item.shortname"
}
},
{
"furnace.shortname", new List<string>
{
"item.shortname"
}
}
};
[JsonProperty(PropertyName = "Smelting Frequencies (Smelt items every N smelting ticks)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> SmeltingFrequencies = new Dictionary<string, int>
{
{"global", 1},
{"furnace.shortname", 1}
};
[JsonProperty(PropertyName = "Debug")]
public bool Debug = false;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
}
catch
{
PrintError("Your configuration file contains an error. Using default configuration values.");
LoadDefaultConfig();
}
}
protected override void LoadDefaultConfig() => _config = new Configuration();
protected override void SaveConfig() => Config.WriteObject(_config);
#endregion
#region Hooks
private void Unload()
{
var ovens = UnityEngine.Object.FindObjectsOfType<BaseOven>();
PrintDebug($"Processing BaseOven(s).. Amount: {ovens.Length}.");
for (var i = 0; i < ovens.Length; i++)
{
var oven = ovens[i];
var component = oven.GetComponent<FurnaceController>();
if (oven.IsOn())
{
PrintDebug("Oven is on. Restarted cooking");
component.StopCooking();
oven.StartCooking();
}
UnityEngine.Object.Destroy(component);
}
PrintDebug("Done.");
}
private void OnServerInitialized()
{
_instance = this;
permission.RegisterPermission(PermissionUse, this);
var ovens = UnityEngine.Object.FindObjectsOfType<BaseOven>();
PrintDebug($"Processing BaseOven(s).. Amount: {ovens.Length}.");
for (var i = 0; i < ovens.Length; i++)
{
var oven = ovens[i];
OnEntitySpawned(oven);
}
timer.Once(1f, () =>
{
for (var i = 0; i < ovens.Length; i++)
{
var oven = ovens[i];
var component = oven.gameObject.GetComponent<FurnaceController>();
if (oven == null || oven.IsDestroyed || !oven.IsOn() || !CanUse(oven.OwnerID))
continue;
component.StartCooking();
}
});
}
private void OnEntitySpawned(BaseNetworkable entity)
{
var oven = entity as BaseOven;
if (oven == null)
return;
oven.gameObject.AddComponent<FurnaceController>();
}
private object OnOvenToggle(StorageContainer oven, BasePlayer player)
{
if (oven is BaseFuelLightSource || oven.needsBuildingPrivilegeToUse && !player.CanBuild())
return null;
PrintDebug("OnOvenToggle called");
var component = oven.gameObject.GetComponent<FurnaceController>();
var canUse = CanUse(oven.OwnerID) || CanUse(player.userID);
if (oven.IsOn())
{
component.StopCooking();
}
else
{
if (canUse)
component.StartCooking();
else
{
PrintDebug($"No permission ({player.userID})");
return null;
}
}
return false;
}
#endregion
#region Helpers
private bool CanUse(ulong id) =>
!_config.UsePermission || permission.UserHasPermission(id.ToString(), PermissionUse);
private static void PrintDebug(string message)
{
if (_config.Debug)
Debug.Log($"DEBUG ({_instance.Name}) > " + message);
}
#endregion
#region Controller
public class FurnaceController : FacepunchBehaviour
{
private int _ticks;
private BaseOven _oven;
private BaseOven Furnace
{
get
{
if (_oven == null)
_oven = GetComponent<BaseOven>();
return _oven;
}
}
private float _speedMultiplier;
private float _fuelSpeedMultiplier;
private int _fuelUsageMultiplier;
private int _smeltingFrequency;
private Dictionary<string, float> _outputModifiers;
private float OutputMultiplier(string shortname)
{
float modifier;
if (_outputModifiers == null || !_outputModifiers.TryGetValue(shortname, out modifier) &&
!_outputModifiers.TryGetValue("global", out modifier))
modifier = 1.0f;
PrintDebug($"{shortname} modifier: {modifier}");
return modifier;
}
private List<string> _blacklist;
private List<string> _whitelist;
private bool? IsAllowed(string shortname)
{
if (_blacklist != null && _blacklist.Contains(shortname))
return false;
if (_whitelist != null && _whitelist.Contains(shortname))
return true;
return null;
}
private void Awake()
{
// Well, sorry for my complicated code. But that should work faster! :)
float modifierF; // float modifier
int modifierI; // int modifier
if (!_config.SpeedMultipliers.TryGetValue(Furnace.ShortPrefabName, out modifierF) &&
!_config.SpeedMultipliers.TryGetValue("global", out modifierF))
modifierF = 1.0f;
_speedMultiplier = 0.5f / modifierF;
if (!_config.FuelSpeedMultipliers.TryGetValue(Furnace.ShortPrefabName, out modifierF) &&
!_config.FuelSpeedMultipliers.TryGetValue("global", out modifierF))
modifierF = 1.0f;
_fuelSpeedMultiplier = modifierF;
if (!_config.FuelUsageMultipliers.TryGetValue(Furnace.ShortPrefabName, out modifierI) &&
!_config.FuelUsageMultipliers.TryGetValue("global", out modifierI))
modifierI = 1;
_fuelUsageMultiplier = modifierI;
if (!_config.SmeltingFrequencies.TryGetValue(Furnace.ShortPrefabName, out modifierI) &&
!_config.SmeltingFrequencies.TryGetValue("global", out modifierI))
modifierI = 1;
_smeltingFrequency = modifierI;
if (!_config.OutputMultipliers.TryGetValue(Furnace.ShortPrefabName, out _outputModifiers) && !_config.OutputMultipliers.TryGetValue("global", out _outputModifiers))
{
// ignored
}
if ((!_config.Blacklist.TryGetValue(Furnace.ShortPrefabName, out _blacklist) &&
!_config.Blacklist.TryGetValue("global", out _blacklist)) &
(!_config.Whitelist.TryGetValue(Furnace.ShortPrefabName, out _whitelist) &&
!_config.Whitelist.TryGetValue("global", out _whitelist)))
{
// ignored
}
}
private Item FindBurnable()
{
if (Furnace.inventory == null)
return null;
foreach (var item in Furnace.inventory.itemList)
{
var component = item.info.GetComponent<ItemModBurnable>();
if (component && (Furnace.fuelType == null || item.info == Furnace.fuelType))
{
return item;
}
}
return null;
}
public void Cook()
{
var item = FindBurnable();
if (item == null)
{
StopCooking();
return;
}
SmeltItems();
var slot = Furnace.GetSlot(BaseEntity.Slot.FireMod);
if (slot)
{
slot.SendMessage("Cook", 0.5f, SendMessageOptions.DontRequireReceiver);
}
var component = item.info.GetComponent<ItemModBurnable>();
item.fuel -= 0.5f * (Furnace.cookingTemperature / 200f) * _fuelSpeedMultiplier;
if (!item.HasFlag(global::Item.Flag.OnFire))
{
item.SetFlag(global::Item.Flag.OnFire, true);
item.MarkDirty();
}
if (item.fuel <= 0f)
{
ConsumeFuel(item, component);
}
_ticks++;
}
private void ConsumeFuel(Item fuel, ItemModBurnable burnable)
{
if (Furnace.allowByproductCreation && burnable.byproductItem != null && Random.Range(0f, 1f) > burnable.byproductChance)
{
var def = burnable.byproductItem;
var item = ItemManager.Create(def, (int) (burnable.byproductAmount * OutputMultiplier(def.shortname))); // It's fuel multiplier
if (!item.MoveToContainer(Furnace.inventory))
{
StopCooking();
item.Drop(Furnace.inventory.dropPosition, Furnace.inventory.dropVelocity);
}
}
if (fuel.amount <= 1)
{
fuel.Remove();
return;
}
fuel.amount -= _fuelUsageMultiplier;
fuel.fuel = burnable.fuelAmount;
fuel.MarkDirty();
}
private void SmeltItems()
{
if (_ticks % _smeltingFrequency != 0)
return;
for (var i = 0; i < Furnace.inventory.itemList.Count; i++)
{
// Getting item and checking if it's valid
var item = Furnace.inventory.itemList[i];
if (item == null || !item.IsValid())
continue;
// Getting cookable
var cookable = item.info.GetComponent<ItemModCookable>();
if (cookable == null)
continue;
// Checking if item's cooking is allowed
var isAllowed = IsAllowed(item.info.shortname);
if (isAllowed != null && !isAllowed.Value) // Allowed is false? Okay, no problem. Don't cook this item
continue;
// What about temperature?
// This lets us deny cooking, for example, meat in furnaces
var temperature = item.temperature;
if ((temperature < cookable.lowTemp || temperature > cookable.highTemp) && isAllowed == null) // Not allowed, not denied? That's our case! Because if it's allowed, this function won't be executed :P
{
if (!cookable.setCookingFlag || !item.HasFlag(global::Item.Flag.Cooking)) continue;
item.SetFlag(global::Item.Flag.Cooking, false);
item.MarkDirty();
continue;
}
// So, so.. what about items' cooking speed (time)?
if (cookable.cookTime > 0 && _ticks * 1f / _smeltingFrequency % cookable.cookTime > 0)
continue;
// Setting cooking flag
if (cookable.setCookingFlag && !item.HasFlag(global::Item.Flag.Cooking))
{
item.SetFlag(global::Item.Flag.Cooking, true);
item.MarkDirty();
}
// Changing amount
var position = item.position;
if (item.amount > 1)
{
item.amount--;
item.MarkDirty();
}
else
{
item.Remove();
}
// What if nothing is produced?
if (cookable.becomeOnCooked == null) continue;
// Let's create an item!
var item2 = ItemManager.Create(cookable.becomeOnCooked,
(int) (cookable.amountOfBecome * OutputMultiplier(cookable.becomeOnCooked.shortname))); // It's an another one output multiplier, but not for fuel
// Some checks
if (item2 == null || item2.MoveToContainer(item.parent, position) ||
item2.MoveToContainer(item.parent))
continue;
// Dropping item and stopping cooking if oven is full
item2.Drop(item.parent.dropPosition, item.parent.dropVelocity);
if (!item.parent.entityOwner) continue;
StopCooking();
}
}
public void StartCooking()
{
if (FindBurnable() == null)
{
PrintDebug("No burnable.");
return;
}
StopCooking();
PrintDebug("Starting cooking..");
Furnace.inventory.temperature = Furnace.cookingTemperature;
Furnace.UpdateAttachmentTemperature();
PrintDebug($"Speed Multiplier: {_speedMultiplier}");
Furnace.InvokeRepeating(Cook, _speedMultiplier, _speedMultiplier);
Furnace.SetFlag(BaseEntity.Flags.On, true);
}
public void StopCooking()
{
PrintDebug("Stopping cooking..");
Furnace.CancelInvoke(Cook);
Furnace.StopCooking();
}
}
#endregion
}
}

1275
plugins/QuickSort.cs Normal file

File diff suppressed because it is too large Load Diff

3353
plugins/RemoverTool.cs Normal file

File diff suppressed because it is too large Load Diff

1933
plugins/SkinBox.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
using System.Collections.Generic;
using System.Linq;
using System;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Stack Size Controller", "Canopy Sheep", "2.0.4", ResourceId = 2320)]
[Description("Allows you to set the max stack size of every item.")]
public class StackSizeController : RustPlugin
{
#region Data
private bool pluginLoaded = false;
Items items;
class Items
{
public Dictionary<string, int> itemlist = new Dictionary<string, int>();
}
private bool LoadData()
{
var itemsdatafile = Interface.Oxide.DataFileSystem.GetFile("StackSizeController");
try
{
items = itemsdatafile.ReadObject<Items>();
return true;
}
catch (Exception ex)
{
PrintWarning("Error: Data file is corrupt. Debug info: " + ex.Message);
return false;
}
}
private void UpdateItems()
{
var gameitemList = ItemManager.itemList;
List<string> itemCategories = new List<string>();
int stacksize;
foreach (var item in gameitemList)
{
if (!itemCategories.Contains(item.category.ToString()))
{
if (!(configData.Settings.CategoryDefaultStack.ContainsKey(item.category.ToString())))
{
configData.Settings.CategoryDefaultStack[item.category.ToString()] = configData.Settings.NewCategoryDefaultSetting;
Puts("Added item category: '" + item.category.ToString() + "' to the config.");
}
itemCategories.Add(item.category.ToString());
}
if (!(items.itemlist.ContainsKey(item.displayName.english)))
{
stacksize = DetermineStack(item);
items.itemlist.Add(item.displayName.english, stacksize);
}
}
List<string> KeysToRemove = new List<string>();
foreach (KeyValuePair<string ,int> category in configData.Settings.CategoryDefaultStack)
{
if (!itemCategories.Contains(category.Key)) { KeysToRemove.Add(category.Key); }
}
if (KeysToRemove.Count > 0)
{
Puts("Cleaning config categories...");
foreach (string Key in KeysToRemove)
{
configData.Settings.CategoryDefaultStack.Remove(Key);
}
}
SaveConfig();
KeysToRemove = new List<string>();
bool foundItem = false;
foreach (KeyValuePair<string, int> item in items.itemlist)
{
foreach (var itemingamelist in gameitemList)
{
if (itemingamelist.displayName.english == item.Key)
{
foundItem = true;
break;
}
}
if (!(foundItem)) { KeysToRemove.Add(item.Key); }
foundItem = false;
}
if (KeysToRemove.Count > 0)
{
Puts("Cleaning data file...");
foreach (string key in KeysToRemove)
{
items.itemlist.Remove(key);
}
}
SaveData();
LoadStackSizes();
}
private int DetermineStack(ItemDefinition item)
{
if (item.condition.enabled && item.condition.max > 0 && (!configData.Settings.StackHealthItems))
{
return 1;
}
else
{
if (configData.Settings.DefaultStack != 0 && (!configData.Settings.CategoryDefaultStack.ContainsKey(item.category.ToString())))
{
return configData.Settings.DefaultStack;
}
else if (configData.Settings.CategoryDefaultStack.ContainsKey(item.category.ToString()) && configData.Settings.CategoryDefaultStack[item.category.ToString()] != 0)
{
return configData.Settings.CategoryDefaultStack[item.category.ToString()];
}
else if (configData.Settings.DefaultStack != 0 && configData.Settings.CategoryDefaultStack[item.category.ToString()] == 0)
{
return configData.Settings.DefaultStack;
}
else
{
return item.stackable;
}
}
}
private void LoadStackSizes()
{
var gameitemList = ItemManager.itemList;
foreach (var item in gameitemList)
{
item.stackable = items.itemlist[item.displayName.english];
}
}
private void SaveData()
{
Interface.Oxide.DataFileSystem.WriteObject("StackSizeController", items);
}
#endregion
#region Config
ConfigData configData;
class ConfigData
{
public SettingsData Settings { get; set; }
}
class SettingsData
{
public int DefaultStack { get; set; }
public int NewCategoryDefaultSetting { get; set; }
public bool StackHealthItems { get; set; }
public Dictionary<string, int> CategoryDefaultStack { get; set; }
}
private void TryConfig()
{
try
{
configData = Config.ReadObject<ConfigData>();
}
catch (Exception ex)
{
PrintWarning("Corrupt config detected, debug: " + ex.Message);
LoadDefaultConfig();
}
}
protected override void LoadDefaultConfig()
{
Puts("Generating a new config file...");
Config.WriteObject(new ConfigData
{
Settings = new SettingsData
{
DefaultStack = 0,
NewCategoryDefaultSetting = 0,
StackHealthItems = true,
CategoryDefaultStack = new Dictionary<string, int>()
{
{ "Ammunition", 0 },
{ "Weapon", 0 },
},
},
}, true);
}
private void SaveConfig()
{
Config.WriteObject(configData);
}
#endregion
#region Hooks
private void OnServerInitialized()
{
TryConfig();
pluginLoaded = LoadData();
if (pluginLoaded)
{
if (!configData.Settings.StackHealthItems) { Unsubscribe(); }
UpdateItems();
}
else { Puts("Stack Sizes could not be changed due to a corrupt data file."); }
permission.RegisterPermission("stacksizecontroller.canChangeStackSize", this);
}
private bool hasPermission(BasePlayer player, string perm)
{
if (player.net.connection.authLevel > 1)
{
return true;
}
return permission.UserHasPermission(player.userID.ToString(), perm);
}
private object CanStackItem(Item item, Item targetItem)
{
if (item.info.shortname != targetItem.info.shortname) { return null; }
if (item.contents != targetItem.contents) { return false; }
FlameThrower flamethrower = item.GetHeldEntity() as FlameThrower;
if (flamethrower != null)
{
if (flamethrower.ammo != (targetItem.GetHeldEntity() as FlameThrower).ammo) { return false; }
}
return null;
}
private void Unsubscribe()
{
Unsubscribe(nameof(CanStackItem));
}
#endregion
#region Commands
[ChatCommand("stack")]
private void StackCommand(BasePlayer player, string command, string[] args)
{
if (!hasPermission(player, "stacksizecontroller.canChangeStackSize"))
{
SendReply(player, "You don't have permission to use this command.");
return;
}
if (!pluginLoaded)
{
SendReply(player, "StackSizeController has encountered an error while trying to read the data file. Please contact your server administrator to fix the issue.");
return;
}
if (args.Length < 2)
{
SendReply(player, "Syntax Error: Requires 2 arguments. Syntax Example: /stack ammo.rocket.hv 64 (Use shortname)");
return;
}
int stackAmount = 0;
List<ItemDefinition> gameitems = ItemManager.itemList.FindAll(x => x.shortname.Equals(args[0]));
if (gameitems.Count == 0)
{
SendReply(player, "Syntax Error: That is an incorrect item name. Please use a valid shortname.");
return;
}
string replymessage = "";
switch (args[1].ToLower())
{
case "default":
{
stackAmount = DetermineStack(gameitems[0]);
replymessage = "Updated Stack Size for " + gameitems[0].displayName.english + " (" + gameitems[0].shortname + ") to " + stackAmount + " (Default value based on config).";
break;
}
default:
{
if (int.TryParse(args[1], out stackAmount) == false)
{
SendReply(player, "Syntax Error: Stack Amount is not a number. Syntax Example: /stack ammo.rocket.hv 64 (Use shortname)");
return;
}
replymessage = "Updated Stack Size for " + gameitems[0].displayName.english + " (" + gameitems[0].shortname + ") to " + stackAmount + ".";
break;
}
}
if (gameitems[0].condition.enabled && gameitems[0].condition.max > 0)
{
if (!(configData.Settings.StackHealthItems))
{
SendReply(player, "Error: Stacking health items is disabled in the config.");
return;
}
}
items.itemlist[gameitems[0].displayName.english] = Convert.ToInt32(stackAmount);
gameitems[0].stackable = Convert.ToInt32(stackAmount);
SaveData();
SendReply(player, replymessage);
}
[ChatCommand("stackall")]
private void StackAllCommand(BasePlayer player, string command, string[] args)
{
if (!hasPermission(player, "stacksizecontroller.canChangeStackSize"))
{
SendReply(player, "You don't have permission to use this command.");
return;
}
if (!pluginLoaded)
{
SendReply(player, "StackSizeController has encountered an error while trying to read the data file. Please contact your server administrator to fix the issue.");
return;
}
if (args.Length < 1)
{
SendReply(player, "Syntax Error: Requires 1 argument. Syntax Example: /stackall 65000");
return;
}
int stackAmount = 0;
string replymessage = "";
var itemList = ItemManager.itemList;
foreach (var gameitem in itemList)
{
switch (args[0].ToLower())
{
case "default":
{
stackAmount = DetermineStack(gameitem);
replymessage = "The Stack Size of all stackable items has been set to their default values (specified in config).";
break;
}
default:
{
if (int.TryParse(args[0], out stackAmount) == false)
{
SendReply(player, "Syntax Error: Stack Amount is not a number. Syntax Example: /stackall 65000");
return;
}
replymessage = "The Stack Size of all stackable items has been set to " + stackAmount.ToString() + ".";
break;
}
}
if (gameitem.condition.enabled && gameitem.condition.max > 0 && !(configData.Settings.StackHealthItems)) { continue; }
if (gameitem.displayName.english.ToString() == "Salt Water" || gameitem.displayName.english.ToString() == "Water") { continue; }
items.itemlist[gameitem.displayName.english] = Convert.ToInt32(stackAmount);
gameitem.stackable = Convert.ToInt32(stackAmount);
}
SaveData();
SendReply(player, replymessage);
}
[ConsoleCommand("stack")]
private void StackConsoleCommand(ConsoleSystem.Arg arg)
{
if (arg.IsAdmin != true)
{
if ((arg.Connection.userid.ToString() != null) && !(permission.UserHasPermission(arg.Connection.userid.ToString(), "stacksizecontroller.canChangeStackSize")))
{
arg.ReplyWith("[StackSizeController] You don't have permission to use this command.");
return;
}
}
if (!pluginLoaded)
{
arg.ReplyWith("[StackSizeController] StackSizeController has encountered an error while trying to read the data file. Please contact your server administrator to fix the issue.");
return;
}
if (arg.Args != null)
{
if (arg.Args.Length < 2)
{
arg.ReplyWith("[StackSizeController] Syntax Error: Requires 2 arguments. Syntax Example: stack ammo.rocket.hv 64 (Use shortname)");
return;
}
}
else
{
arg.ReplyWith("[StackSizeController] Syntax Error: Requires 2 arguments. Syntax Example: stack ammo.rocket.hv 64 (Use shortname)");
return;
}
int stackAmount = 0;
List<ItemDefinition> gameitems = ItemManager.itemList.FindAll(x => x.shortname.Equals(arg.Args[0]));
if (gameitems.Count == 0)
{
arg.ReplyWith("[StackSizeController] Syntax Error: That is an incorrect item name. Please use a valid shortname.");
return;
}
string replymessage = "";
switch (arg.Args[1].ToLower())
{
case "default":
{
stackAmount = DetermineStack(gameitems[0]);
replymessage = "[StackSizeController] Updated Stack Size for " + gameitems[0].displayName.english + " (" + gameitems[0].shortname + ") to " + stackAmount + " (Default value based on config).";
break;
}
default:
{
if (int.TryParse(arg.Args[1], out stackAmount) == false)
{
arg.ReplyWith("[StackSizeController] Syntax Error: Stack Amount is not a number. Syntax Example: /stack ammo.rocket.hv 64 (Use shortname)");
return;
}
replymessage = "[StackSizeController] Updated Stack Size for " + gameitems[0].displayName.english + " (" + gameitems[0].shortname + ") to " + stackAmount + ".";
break;
}
}
if (gameitems[0].condition.enabled && gameitems[0].condition.max > 0)
{
if (!(configData.Settings.StackHealthItems))
{
arg.ReplyWith("[StackSizeController] Error: Stacking health items is disabled in the config.");
return;
}
}
items.itemlist[gameitems[0].displayName.english] = Convert.ToInt32(stackAmount);
gameitems[0].stackable = Convert.ToInt32(stackAmount);
SaveData();
arg.ReplyWith(replymessage);
}
[ConsoleCommand("stackall")]
private void StackAllConsoleCommand(ConsoleSystem.Arg arg)
{
if (arg.IsAdmin != true)
{
if ((arg.Connection.userid.ToString() != null) && !(permission.UserHasPermission(arg.Connection.userid.ToString(), "stacksizecontroller.canChangeStackSize")))
{
arg.ReplyWith("[StackSizeController] You don't have permission to use this command.");
return;
}
}
if (!pluginLoaded)
{
arg.ReplyWith("[StackSizeController] StackSizeController has encountered an error while trying to read the data file. Please contact your server administrator to fix the issue.");
return;
}
if (arg.Args != null)
{
if (arg.Args.Length < 1)
{
arg.ReplyWith("[StackSizeController] Syntax Error: Requires 1 argument. Syntax Example: stackall 65000");
return;
}
}
else
{
arg.ReplyWith("[StackSizeController] Syntax Error: Requires 1 argument. Syntax Example: stackall 65000");
return;
}
int stackAmount = 0;
string replymessage = "";
var itemList = ItemManager.itemList;
foreach (var gameitem in itemList)
{
if (gameitem.condition.enabled && gameitem.condition.max > 0 && (!(configData.Settings.StackHealthItems))) { continue; }
if (gameitem.displayName.english.ToString() == "Salt Water" ||
gameitem.displayName.english.ToString() == "Water") { continue; }
switch (arg.Args[0].ToLower())
{
case "default":
{
stackAmount = DetermineStack(gameitem);
replymessage = "[StackSizeController] The Stack Size of all stackable items has been set to their default values (specified in config).";
break;
}
default:
{
if (int.TryParse(arg.Args[0], out stackAmount) == false)
{
arg.ReplyWith("[StackSizeController] Syntax Error: Stack Amount is not a number. Syntax Example: /stackall 65000");
return;
}
replymessage = "[StackSizeController] The Stack Size of all stackable items has been set to " + stackAmount.ToString() + ".";
break;
}
}
items.itemlist[gameitem.displayName.english] = Convert.ToInt32(stackAmount);
gameitem.stackable = Convert.ToInt32(stackAmount);
}
SaveData();
arg.ReplyWith(replymessage);
}
#endregion
}
}

355
plugins/TimeOfDay.cs Normal file
View File

@ -0,0 +1,355 @@
using Oxide.Core.Plugins;
using Oxide.Core;
using System;
using System.Text;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("TimeOfDay", "FuJiCuRa", "2.3.4")]
[Description("Does alter day and night duration.")]
public class TimeOfDay : RustPlugin
{
bool Changed;
bool Initialized;
int componentSearchAttempts;
TOD_Time timeComponent;
bool activatedDay;
int authLevelCmds;
int authLevelFreeze;
int dayLength;
int nightLength;
int presetDay;
int presetMonth;
int presetYear;
bool setPresetDate;
bool freezeDate;
bool autoSkipNight;
bool autoSkipDay;
bool logAutoSkipConsole;
bool freezeTimeOnload;
float timeToFreeze;
object GetConfig(string menu, string datavalue, object defaultValue)
{
var data = Config[menu] as Dictionary<string, object>;
if (data == null)
{
data = new Dictionary<string, object>();
Config[menu] = data;
Changed = true;
}
object value;
if (!data.TryGetValue(datavalue, out value))
{
value = defaultValue;
data[datavalue] = value;
Changed = true;
}
return value;
}
void LoadVariables()
{
dayLength = System.Convert.ToInt32(GetConfig("Settings", "dayLength", 30));
nightLength = System.Convert.ToInt32(GetConfig("Settings", "nightLength", 30));
freezeDate = System.Convert.ToBoolean(GetConfig("Settings", "freezeDate", false));
authLevelCmds = System.Convert.ToInt32(GetConfig("Settings", "authLevelCmds", 1));
authLevelFreeze = System.Convert.ToInt32(GetConfig("Settings", "authLevelFreeze", 2));
autoSkipNight = System.Convert.ToBoolean(GetConfig("Settings", "autoSkipNight", false));
autoSkipDay = System.Convert.ToBoolean(GetConfig("Settings", "autoSkipDay", false));
logAutoSkipConsole = System.Convert.ToBoolean(GetConfig("Settings", "logAutoSkipConsole", true));
presetDay = System.Convert.ToInt32(GetConfig("DatePreset", "presetDay", 1));
presetMonth = System.Convert.ToInt32(GetConfig("DatePreset", "presetMonth", 1));
presetYear = System.Convert.ToInt32(GetConfig("DatePreset", "presetYear", 2020));
setPresetDate = System.Convert.ToBoolean(GetConfig("DatePreset", "setPresetDate", false));
freezeTimeOnload = System.Convert.ToBoolean(GetConfig("TimeFreeze", "freezeTimeOnload", false));
timeToFreeze = System.Convert.ToSingle(GetConfig("TimeFreeze", "timeToFreeze", 12.0));
if (!Changed) return;
SaveConfig();
Changed = false;
}
protected override void LoadDefaultConfig()
{
Config.Clear();
LoadVariables();
}
void Loaded()
{
LoadVariables();
Initialized = false;
}
void Unload()
{
if (timeComponent == null || !Initialized) return;
timeComponent.OnSunrise -= OnSunrise;
timeComponent.OnSunset -= OnSunset;
timeComponent.OnDay -= OnDay;
timeComponent.OnHour -= OnHour;
}
void OnServerInitialized()
{
if (TOD_Sky.Instance == null)
{
componentSearchAttempts++;
if (componentSearchAttempts < 10)
timer.Once(1, OnServerInitialized);
else
PrintWarning("Could not find required component after 10 attempts. Plugin disabled");
return;
}
timeComponent = TOD_Sky.Instance.Components.Time;
if (timeComponent == null)
{
PrintWarning("Could not fetch time component. Plugin disabled");
return;
}
if (setPresetDate)
{
TOD_Sky.Instance.Cycle.Day = presetDay;
TOD_Sky.Instance.Cycle.Month = presetMonth;
TOD_Sky.Instance.Cycle.Year = presetYear;
}
SetTimeComponent();
if (freezeTimeOnload)
StartupFreeze();
}
void SetTimeComponent()
{
timeComponent.ProgressTime = true;
timeComponent.UseTimeCurve = false;
timeComponent.OnSunrise += OnSunrise;
timeComponent.OnSunset += OnSunset;
timeComponent.OnDay += OnDay;
timeComponent.OnHour += OnHour;
Initialized = true;
if (TOD_Sky.Instance.Cycle.Hour > TOD_Sky.Instance.SunriseTime && TOD_Sky.Instance.Cycle.Hour < TOD_Sky.Instance.SunsetTime)
OnSunrise();
else
OnSunset();
}
void StartupFreeze()
{
if (!Initialized) return;
timeComponent.ProgressTime = false;
ConVar.Env.time = timeToFreeze;
}
void OnDay()
{
if (Initialized && freezeDate)
--TOD_Sky.Instance.Cycle.Day;
}
void OnHour()
{
if (!Initialized) return;
if (TOD_Sky.Instance.Cycle.Hour > TOD_Sky.Instance.SunriseTime && TOD_Sky.Instance.Cycle.Hour < TOD_Sky.Instance.SunsetTime && !activatedDay)
{
OnSunrise();
return;
}
if ((TOD_Sky.Instance.Cycle.Hour > TOD_Sky.Instance.SunsetTime || TOD_Sky.Instance.Cycle.Hour < TOD_Sky.Instance.SunriseTime) && activatedDay)
{
OnSunset();
return;
}
}
void OnSunrise()
{
if (!Initialized) return;
if (autoSkipDay && !autoSkipNight)
{
TOD_Sky.Instance.Cycle.Hour = TOD_Sky.Instance.SunsetTime;
if (logAutoSkipConsole)
Puts("Daytime autoskipped");
OnSunset();
return;
}
timeComponent.DayLengthInMinutes = dayLength * (24.0f / (TOD_Sky.Instance.SunsetTime - TOD_Sky.Instance.SunriseTime));
if (!activatedDay)
Interface.CallHook("OnTimeSunrise");
activatedDay = true;
}
void OnSunset()
{
if (!Initialized) return;
if (autoSkipNight)
{
float timeToAdd = (24 - TOD_Sky.Instance.Cycle.Hour) + TOD_Sky.Instance.SunriseTime;
TOD_Sky.Instance.Cycle.Hour += timeToAdd;
if (logAutoSkipConsole)
Puts("Nighttime autoskipped");
OnSunrise();
return;
}
timeComponent.DayLengthInMinutes = nightLength * (24.0f / (24.0f - (TOD_Sky.Instance.SunsetTime - TOD_Sky.Instance.SunriseTime)));
if (activatedDay)
Interface.CallHook("OnTimeSunset");
activatedDay = false;
}
[ConsoleCommand("tod.daylength")]
void ConsoleDayLength(ConsoleSystem.Arg arg)
{
if (!Initialized) return;
if (arg.Connection != null && arg.Connection.authLevel < authLevelCmds) return;
if (arg.Args == null || arg.Args.Length < 1)
{
SendReply(arg, $"Current 'dayLength' setting is '{dayLength}'");
return;
}
int newDaylength = 0;
if (int.TryParse(arg.Args[0], out newDaylength))
{
if (newDaylength < 1)
{
SendReply(arg, $"The new daylength must be greater zero");
return;
}
}
dayLength = newDaylength;
SendReply(arg, $"The 'dayLength' has been set to '{dayLength}'");
if (TOD_Sky.Instance.IsDay)
OnSunrise();
else
OnSunset();
Config["Settings", "dayLength"] = dayLength;
SaveConfig();
}
[ConsoleCommand("tod.nightlength")]
void ConsoleNightLength(ConsoleSystem.Arg arg)
{
if (!Initialized) return;
if (arg.Connection != null && arg.Connection.authLevel < authLevelCmds) return;
if (arg.Args == null || arg.Args.Length < 1)
{
SendReply(arg, $"Current 'nightLength' setting is '{nightLength}'");
return;
}
int newNightlength = 0;
if (int.TryParse(arg.Args[0], out newNightlength))
{
if (newNightlength < 1)
{
SendReply(arg, $"The new nightlength must be greater zero");
return;
}
}
nightLength = newNightlength;
SendReply(arg, $"The 'nightLength' has been set to '{nightLength}'");
if (TOD_Sky.Instance.IsDay)
OnSunrise();
else
OnSunset();
Config["Settings", "nightLength"] = nightLength;
SaveConfig();
}
[ConsoleCommand("tod.freezetime")]
void ConsoleFreezeTime(ConsoleSystem.Arg arg)
{
if (!Initialized) return;
if (arg.Connection != null && arg.Connection.authLevel < authLevelFreeze) return;
timeComponent.ProgressTime = !timeComponent.ProgressTime;
if (timeComponent.ProgressTime)
SendReply(arg, $"The game time was unfreezed");
else
SendReply(arg, $"The game time was freezed");
}
[ConsoleCommand("tod.skipday")]
void ConsoleSkipDay(ConsoleSystem.Arg arg)
{
if (!Initialized) return;
if (arg.Connection != null && arg.Connection.authLevel < authLevelCmds) return;
if (TOD_Sky.Instance.IsNight)
{
SendReply(arg, $"Night is already active");
return;
}
OnSunset();
TOD_Sky.Instance.Cycle.Hour = TOD_Sky.Instance.SunsetTime;
SendReply(arg, $"Current daytime skipped");
}
[ConsoleCommand("tod.skipnight")]
void ConsoleSkipNight(ConsoleSystem.Arg arg)
{
if (!Initialized) return;
if (arg.Connection != null && arg.Connection.authLevel < authLevelCmds) return;
if (TOD_Sky.Instance.IsDay)
{
SendReply(arg, $"Day is already active");
return;
}
OnSunrise();
TOD_Sky.Instance.Cycle.Hour = TOD_Sky.Instance.SunriseTime;
SendReply(arg, $"Current nighttime skipped");
}
[ChatCommand("tod")]
private void TodCommand(BasePlayer player, string command, string[] args)
{
if (!Initialized)
return;
TimeSpan ts1= TimeSpan.FromHours(TOD_Sky.Instance.SunriseTime);
TimeSpan ts2= TimeSpan.FromHours(TOD_Sky.Instance.SunsetTime);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine(FormNeutralMessage("-------- Settings --------"));
stringBuilder.AppendLine("Current Time".PadRight(15) + TOD_Sky.Instance.Cycle.DateTime.ToString("HH:mm:ss"));
stringBuilder.AppendLine("Sunrise Hour".PadRight(15) + string.Format("{0}:{1}", System.Math.Truncate(ts1.TotalHours).ToString(), ts1.Minutes.ToString()));
stringBuilder.AppendLine("Sunset Hour".PadRight(15) + string.Format("{0}:{1}", System.Math.Truncate(ts2.TotalHours).ToString(), ts2.Minutes.ToString()));
stringBuilder.AppendLine("Daylength".PadRight(15) + dayLength.ToString() + " minutes");
stringBuilder.Append("Nightlength".PadRight(15) + nightLength.ToString() + " minutes");
PrintPluginMessageToChat(player, stringBuilder.ToString().TrimEnd());
}
[HookMethod("SendHelpText")]
private void SendHelpText(BasePlayer player)
{
if (!Initialized) return;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(FormNeutralMessage("-------------------- Available Commands --------------------\n"));
stringBuilder.Append(FormNeutralMessage("/tod") + " - Shows current Time Of Day.\n");
PrintPluginMessageToChat(player, stringBuilder.ToString());
}
private void PrintPluginMessageToChat(BasePlayer player, string message)
{
PrintToChat(player, "<b><size=16>[<color=#ffa500ff>" + this.Name + "</color>]</size></b>\n" + message);
}
private void PrintPluginMessageToChat(string message)
{
PrintToChat("<b><size=16>[<color=#ffa500ff>" + this.Name + "</color>]</size></b>\n" + message);
}
private string FormNeutralMessage(string message)
{
return "<color=#c0c0c0ff>" + message + "</color>";
}
}
}

71
plugins/UnburnableMeat.cs Normal file
View File

@ -0,0 +1,71 @@
using System.Collections.Generic;
namespace Oxide.Plugins
{
[Info("Unburnable Meat", "S642667", "1.0.1")]
[Description("Prevent cooked meats from burning")]
class UnburnableMeat : RustPlugin
{
public static readonly string[] CookedItems = new string[]
{
"bearmeat.cooked",
"chicken.cooked",
"deermeat.cooked",
"horsemeat.cooked",
"humanmeat.cooked",
"meat.pork.cooked",
"wolfmeat.cooked",
"fish.cooked"
};
private Dictionary<string, int> lowTemps = new Dictionary<string, int>();
private Dictionary<string, int> highTemps = new Dictionary<string, int>();
ItemModCookable GetCookable (string shortname)
{
var definition = ItemManager.FindItemDefinition(shortname);
if (definition == null)
{
Puts($"Unknown definition for {shortname}");
return null;
}
var cookable = definition.GetComponent<ItemModCookable>();
if (cookable == null)
{
Puts($"Unknown cookable for {shortname}");
return null;
}
return cookable;
}
void OnServerInitialized()
{
foreach (var shortname in CookedItems)
{
var cookable = GetCookable(shortname);
if (cookable == null)
{
continue;
}
lowTemps.Add(shortname, cookable.lowTemp);
highTemps.Add(shortname, cookable.highTemp);
cookable.lowTemp = -1;
cookable.highTemp = -1;
}
}
void Unload()
{
foreach (KeyValuePair<string, int> item in lowTemps)
{
var cookable = GetCookable(item.Key);
if (cookable == null)
{
continue;
}
cookable.lowTemp = item.Value;
cookable.highTemp = highTemps[item.Key];
}
}
}
}

428
plugins/Vanish.cs Normal file
View File

@ -0,0 +1,428 @@
using Network;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using Rust;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Vanish", "Whispers88", "1.3.8")]
[Description("Allows players with permission to become invisible")]
public class Vanish : RustPlugin
{
#region Configuration
private readonly List<BasePlayer> _hiddenPlayers = new List<BasePlayer>();
private readonly List<BasePlayer> _hiddenOffline = new List<BasePlayer>();
private static List<string> _registeredhooks = new List<string> { "OnNpcTarget", "CanBeTargeted", "CanHelicopterTarget", "CanHelicopterStrafeTarget", "CanBradleyApcTarget", "CanUseLockedEntity", "OnEntityTakeDamage", "OnPlayerDisconnected" };
private static readonly DamageTypeList _EmptyDmgList = new DamageTypeList();
CuiElementContainer cachedVanishUI = null;
private Configuration config;
public class Configuration
{
[JsonProperty("NoClip on Vanish (runs noclip command)")]
public bool NoClipOnVanish = true;
[JsonProperty("Hide an invisible players body under the terrain after disconnect")]
public bool HideOnDisconnect = false;
[JsonProperty("If a player was vanished on disconnection keep them vanished on reconnect")]
public bool HideOnReconnect = true;
[JsonProperty("Turn off fly hack detection for players in vanish")]
public bool AntiFlyHack = true;
[JsonProperty("Enable vanishing and reappearing sound effects")]
public bool EnableSound = true;
[JsonProperty("Make sound effects public")]
public bool PublicSound = false;
[JsonProperty("Enable chat notifications")]
public bool EnableNotifications = true;
[JsonProperty("Sound effect to use when vanishing")]
public string VanishSoundEffect = "assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab";
[JsonProperty("Sound effect to use when reappearing")]
public string ReappearSoundEffect = "assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab";
[JsonProperty("Enable GUI")]
public bool EnableGUI = true;
[JsonProperty("Icon URL (.png or .jpg)")]
public string ImageUrlIcon = "http://i.imgur.com/Gr5G3YI.png";
[JsonProperty("Image Color")]
public string ImageColor = "1 1 1 0.3";
[JsonProperty("Image AnchorMin")]
public string ImageAnchorMin = "0.175 0.017";
[JsonProperty("Image AnchorMax")]
public string ImageAnchorMax = "0.22 0.08";
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null)
{
throw new JsonException();
}
if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys))
{
PrintToConsole("Configuration appears to be outdated; updating and saving");
SaveConfig();
}
}
catch
{
PrintToConsole($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig()
{
PrintToConsole($"Configuration changes saved to {Name}.json");
Config.WriteObject(config, true);
}
#endregion Configuration
#region Localization
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["VanishCommand"] = "vanish",
["CollisionToggle"] = "collider",
["Vanished"] = "Vanish: <color=orange> Enabled </color>",
["Reappear"] = "Vanish: <color=orange> Disabled </color>",
["NoPerms"] = "You do not have permission to do this",
["PermanentVanish"] = "You are in a permanent vanish mode",
["ColliderEnbabled"] = "Player Collider: <color=orange> Enabled </color>",
["ColliderDisabled"] = "Player Collider: <color=orange> Disabled </color>"
}, this);
}
#endregion Localization
#region Initialization
private const string permallow = "vanish.allow";
private const string permunlock = "vanish.unlock";
private const string permdamage = "vanish.damage";
private const string permavanish = "vanish.permanent";
private const string permcollision = "vanish.collision";
private void Init()
{
cachedVanishUI = CreateVanishUI();
// Register univeral chat/console commands
AddLocalizedCommand(nameof(VanishCommand));
AddLocalizedCommand(nameof(CollisionToggle));
// Register permissions for commands
permission.RegisterPermission(permallow, this);
permission.RegisterPermission(permunlock, this);
permission.RegisterPermission(permdamage, this);
permission.RegisterPermission(permavanish, this);
permission.RegisterPermission(permcollision, this);
//Unsubscribe from hooks
UnSubscribeFromHooks();
BasePlayer.activePlayerList.Where(i => HasPerm(i.UserIDString, permavanish) && !IsInvisible(i)).ToList().ForEach(j => Disappear(j));
}
private void Unload()
{
_hiddenPlayers.Where(i => i != null).ToList().ForEach(j => Reappear(j));
}
#endregion Initialization
#region Commands
private void VanishCommand(IPlayer iplayer, string command, string[] args)
{
var player = (BasePlayer)iplayer.Object;
if (!HasPerm(player.UserIDString, permallow))
{
if (config.EnableNotifications) Message(player.IPlayer, "NoPerms");
return;
}
if (HasPerm(player.UserIDString, permavanish))
{
if (config.EnableNotifications) Message(player.IPlayer, "PermanentVanish");
return;
}
if (IsInvisible(player)) Reappear(player);
else Disappear(player);
}
private void CollisionToggle(IPlayer iplayer, string command, string[] args)
{
var player = (BasePlayer)iplayer.Object;
if (!IsInvisible(player)) return;
if (!HasPerm(player.UserIDString, permcollision))
{
if (config.EnableNotifications) Message(player.IPlayer, "NoPerms");
return;
}
var col = player.gameObject.GetComponent<Collider>();
if (!col.enabled)
{
player.EnablePlayerCollider();
Message(player.IPlayer, "ColliderEnbabled");
return;
}
player.DisablePlayerCollider();
Message(player.IPlayer, "ColliderDisabled");
}
private void Reappear(BasePlayer player)
{
if (Interface.CallHook("OnVanishReappear", player) != null) return;
if (config.AntiFlyHack) player.ResetAntiHack();
player._limitedNetworking = false;
player.EnablePlayerCollider();
player.SendNetworkUpdate();
player.GetHeldEntity()?.SendNetworkUpdate();
player.drownEffect.guid = "28ad47c8e6d313742a7a2740674a25b5";
player.fallDamageEffect.guid = "ca14ed027d5924003b1c5d9e523a5fce";
_hiddenPlayers.Remove(player);
if (_hiddenPlayers.Count == 0) UnSubscribeFromHooks();
if (config.EnableSound)
{
if (config.PublicSound)
{
Effect.server.Run(config.ReappearSoundEffect, player.transform.position);
}
else
{
SendEffect(player, config.ReappearSoundEffect);
}
}
CuiHelper.DestroyUi(player, "VanishUI");
if (config.NoClipOnVanish && player.IsFlying) player.SendConsoleCommand("noclip");
if (config.EnableNotifications) Message(player.IPlayer, "Reappear");
}
private void Disappear(BasePlayer player)
{
if (Interface.CallHook("OnVanishDisappear", player) != null) return;
if (config.AntiFlyHack) player.PauseFlyHackDetection();
//Mute Player Effects
player.fallDamageEffect = new GameObjectRef();
player.drownEffect = new GameObjectRef();
AntiHack.ShouldIgnore(player);
if (_hiddenPlayers.Count == 0) SubscribeToHooks();
player._limitedNetworking = true;
player.DisablePlayerCollider();
var connections = Net.sv.connections.Where(con => con.connected && con.isAuthenticated && con.player is BasePlayer && con.player != player).ToList();
player.OnNetworkSubscribersLeave(connections);
_hiddenPlayers.Add(player);
if (config.EnableSound)
{
if (config.PublicSound)
{
Effect.server.Run(config.VanishSoundEffect, player.transform.position);
}
else
{
SendEffect(player, config.VanishSoundEffect);
}
}
if (config.NoClipOnVanish && !player.IsFlying && !player.isMounted) player.SendConsoleCommand("noclip");
if (config.EnableGUI) CuiHelper.AddUi(player, cachedVanishUI);
if (config.EnableNotifications) Message(player.IPlayer, "Vanished");
}
#endregion Commands
#region Hooks
private void OnPlayerConnected(BasePlayer player)
{
if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot))
{
timer.In(3, () => OnPlayerConnected(player));
return;
}
if (_hiddenOffline.Contains(player))
{
_hiddenOffline.Remove(player);
if (HasPerm(player.UserIDString, permallow))
Disappear(player);
}
if (HasPerm(player.UserIDString, permavanish))
{
Disappear(player);
}
}
private object OnNpcTarget(BaseEntity entity, BasePlayer target) => IsInvisible(target) ? (object)true : null;
private object CanBeTargeted(BasePlayer player, MonoBehaviour behaviour) => IsInvisible(player) ? (object)false : null;
private object CanHelicopterTarget(PatrolHelicopterAI heli, BasePlayer player) => IsInvisible(player) ? (object)false : null;
private object CanHelicopterStrafeTarget(PatrolHelicopterAI heli, BasePlayer player) => IsInvisible(player) ? (object)false : null;
private object CanBradleyApcTarget(BradleyAPC apc, BasePlayer player) => IsInvisible(player) ? (object)false : null;
private object CanUseLockedEntity(BasePlayer player, BaseLock baseLock)
{
if (IsInvisible(player))
{
if (HasPerm(player.UserIDString, permunlock)) return true;
if (config.EnableNotifications) Message(player.IPlayer, "NoPerms");
}
return null;
}
private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
{
var attacker = info?.InitiatorPlayer;
var victim = entity?.ToPlayer();
if (!IsInvisible(victim) && !IsInvisible(attacker)) return null;
if (IsInvisible(attacker) && HasPerm(attacker.UserIDString, permdamage)) return null;
if (info != null)
{
info.damageTypes = _EmptyDmgList;
info.HitMaterial = 0;
info.PointStart = Vector3.zero;
info.HitEntity = null;
}
return true;
}
private void OnPlayerDisconnected(BasePlayer player, string reason)
{
if (!IsInvisible(player)) return;
player._limitedNetworking = false;
player.EnablePlayerCollider();
player.SendNetworkUpdate();
player.GetHeldEntity()?.SendNetworkUpdate();
_hiddenPlayers.Remove(player);
if (_hiddenPlayers.Count == 0) UnSubscribeFromHooks();
if (config.HideOnDisconnect)
{
var pos = player.transform.position;
var underTerrainPos = new Vector3(pos.x, TerrainMeta.HeightMap.GetHeight(pos) - 5, pos.z);
player.Teleport(underTerrainPos);
player.DisablePlayerCollider();
}
if (config.HideOnReconnect)
_hiddenOffline.Add(player);
CuiHelper.DestroyUi(player, "VanishUI");
}
#endregion Hooks
#region GUI
private CuiElementContainer CreateVanishUI()
{
CuiElementContainer elements = new CuiElementContainer();
string panel = elements.Add(new CuiPanel
{
Image = { Color = "0.5 0.5 0.5 0.0" },
RectTransform = { AnchorMin = config.ImageAnchorMin, AnchorMax = config.ImageAnchorMax }
}, "Hud.Menu", "VanishUI");
elements.Add(new CuiElement
{
Parent = panel,
Components =
{
new CuiRawImageComponent {Color = config.ImageColor, Url = config.ImageUrlIcon},
new CuiRectTransformComponent {AnchorMin = "0 0", AnchorMax = "1 1"}
}
});
return elements;
}
#endregion GUI
#region Helpers
private void AddLocalizedCommand(string command)
{
foreach (string language in lang.GetLanguages(this))
{
Dictionary<string, string> messages = lang.GetMessages(language, this);
foreach (KeyValuePair<string, string> message in messages)
{
if (!message.Key.Equals(command)) continue;
if (string.IsNullOrEmpty(message.Value)) continue;
AddCovalenceCommand(message.Value, command);
}
}
}
private bool HasPerm(string id, string perm) => permission.UserHasPermission(id, perm);
private string GetLang(string langKey, string playerId = null, params object[] args)
{
return string.Format(lang.GetMessage(langKey, this, playerId), args);
}
private void Message(IPlayer player, string langKey, params object[] args)
{
if (player.IsConnected) player.Message(GetLang(langKey, player.Id, args));
}
private bool IsInvisible(BasePlayer player) => player != null && _hiddenPlayers.Contains(player);
private void UnSubscribeFromHooks()
{
foreach (var hook in _registeredhooks)
Unsubscribe(hook);
}
private void SubscribeToHooks()
{
foreach (var hook in _registeredhooks)
Subscribe(hook);
}
private void SendEffect(BasePlayer player, string sound)
{
var effect = new Effect(sound, player, 0, Vector3.zero, Vector3.forward);
EffectNetwork.Send(effect, player.net.connection);
}
#endregion Helpers
#region Public Helpers
public void _Disappear(BasePlayer basePlayer) => Disappear(basePlayer);
public void _Reappear(BasePlayer basePlayer) => Reappear(basePlayer);
public bool _IsInvisible(BasePlayer basePlayer) => IsInvisible(basePlayer);
#endregion
}
}

198
plugins/WipeKits.cs Normal file
View File

@ -0,0 +1,198 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Wipe Kits", "Ryan", "1.2.51")]
[Description("Puts a configurable cooldown on each kit depending on their kitname.")]
public class WipeKits : RustPlugin
{
#region Declaration
private static ConfigFile _cFile;
private DateTime _cachedWipeTime;
private const string Perm = "wipekits.bypass";
#endregion
#region Config
private class ConfigFile
{
[JsonProperty(PropertyName = "Kit Names & Cooldowns - Cooldowns (minutes)")]
public Dictionary<string, float> Kits;
[JsonProperty(PropertyName = "Use GUI Kits (true/false)")]
public bool UseGui { get; set; }
public static ConfigFile DefaultConfig()
{
return new ConfigFile
{
Kits = new Dictionary<string, float>()
{
["kitname1"] = 5,
["kitname2"] = 5
},
UseGui = false
};
}
}
protected override void LoadDefaultConfig()
{
PrintWarning("Loading default configuration file...");
_cFile = ConfigFile.DefaultConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_cFile = Config.ReadObject<ConfigFile>();
if (_cFile == null)
{
Regenerate();
}
}
catch { Regenerate(); }
}
protected override void SaveConfig() => Config.WriteObject(_cFile);
private void Regenerate()
{
PrintWarning($"Configuration file at 'oxide/config/{Name}.json' seems to be corrupt, regenerating...");
LoadDefaultConfig();
}
#endregion Config
#region Lang
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
// Time formatting
["DayFormat"] = "<color=orange>{0}</color> day and <color=orange>{1}</color> hours",
["DaysFormat"] = "<color=orange>{0}</color> days and <color=orange>{1}</color> hours",
["HourFormat"] = "<color=orange>{0}</color> hour and <color=orange>{1}</color> minutes",
["HoursFormat"] = "<color=orange>{0}</color> hours and <color=orange>{1}</color> minutes",
["MinFormat"] = "<color=orange>{0}</color> minute and <color=orange>{1}</color> seconds",
["MinsFormat"] = "<color=orange>{0}</color> minutes and <color=orange>{1}</color> seconds",
["SecsFormat"] = "<color=orange>{0}</color> seconds",
// Can't use command
["CantUse"] = "The server's just wiped! Try again in {0}",
}, this);
}
#endregion Lang
#region Methods
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
private string GetFormattedTime(double time)
{
var timeSpan = TimeSpan.FromSeconds(time);
if (timeSpan.TotalSeconds < 1)
{
return null;
}
if (Math.Floor(timeSpan.TotalDays) >= 1)
{
return string.Format(timeSpan.Days > 1 ? Lang("DaysFormat", null, timeSpan.Days, timeSpan.Hours) : Lang("DayFormat", null, timeSpan.Days, timeSpan.Hours));
}
if (Math.Floor(timeSpan.TotalMinutes) >= 60)
{
return string.Format(timeSpan.Hours > 1 ? Lang("HoursFormat", null, timeSpan.Hours, timeSpan.Minutes) : Lang("HourFormat", null, timeSpan.Hours, timeSpan.Minutes));
}
if (Math.Floor(timeSpan.TotalSeconds) >= 60)
{
return string.Format(timeSpan.Minutes > 1 ? Lang("MinsFormat", null, timeSpan.Minutes, timeSpan.Seconds) : Lang("MinFormat", null, timeSpan.Minutes, timeSpan.Seconds));
}
return Lang("SecsFormat", null, timeSpan.Seconds);
}
private TimeSpan GetNextKitTime(float cooldown)
{
var timeSince = TimeSpan.FromSeconds((DateTime.UtcNow.ToLocalTime() - _cachedWipeTime).TotalSeconds);
if (timeSince.TotalSeconds > cooldown * 60)
{
return TimeSpan.Zero;
}
double timeUntil = cooldown * 60 - Math.Round(timeSince.TotalSeconds);
return TimeSpan.FromSeconds(timeUntil);
}
#endregion
#region Hooks
private void OnServerInitialized()
{
if(!_cFile.UseGui)
{
Unsubscribe(nameof(OnServerCommand));
}
_cachedWipeTime = SaveRestore.SaveCreatedTime.ToLocalTime();
}
private object OnServerCommand(ConsoleSystem.Arg arg)
{
var player = arg?.Player();
if (player == null || arg.cmd == null)
{
return null;
}
if (arg.cmd.FullName.ToLower().StartsWith("kit.gui") && _cFile.Kits.ContainsKey(arg.GetString(0).ToLower()))
{
float kitCooldown = _cFile.Kits[arg.GetString(0).ToLower()];
if (GetNextKitTime(kitCooldown) != TimeSpan.Zero)
{
player.SendConsoleCommand("kit.close");
PrintToChat(player, Lang("CantUse", player.UserIDString, GetFormattedTime(GetNextKitTime(kitCooldown).TotalSeconds)));
return true;
}
}
return null;
}
private object OnPlayerCommand(BasePlayer player, string command, string[] args)
{
if (command.ToLower() == "kit")
{
float kitCooldown;
if (!args.Any() || !_cFile.Kits.TryGetValue(args[0].Replace("\"", ""), out kitCooldown))
{
return null;
}
if (GetNextKitTime(kitCooldown) == TimeSpan.Zero)
{
return null;
}
PrintToChat(player, Lang("CantUse", player.UserIDString, GetFormattedTime(GetNextKitTime(kitCooldown).TotalSeconds)));
return true;
}
return null;
}
#endregion
}
}