From a1b2880745e0bd7f6f49d12c9737375f18344670 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Fri, 7 Jul 2017 15:46:20 +0800 Subject: [PATCH 1/4] Adding Chinese Localization (#2), credit to DuckSoft * Copying locale en_US to zh_CN * Fully Localized Text --- locales/bsb_zh_CN.yml | 580 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 locales/bsb_zh_CN.yml diff --git a/locales/bsb_zh_CN.yml b/locales/bsb_zh_CN.yml new file mode 100644 index 000000000..c879e3111 --- /dev/null +++ b/locales/bsb_zh_CN.yml @@ -0,0 +1,580 @@ +########################################################################################### +# This is a YML file. Be careful when editing. Check your edits in a YAML checker like # +# the one at http://yaml-online-parser.appspot.com # +########################################################################################### + +### Credits ### +# Tastybento: maintainer +# Poslovitch: maintainer +# DuckSoft: translator +# This translation is adapted to version : [4.0] + +not-setup: + header: |- + 在此插件能正常运作之前, 您需要更多设置... + 请编辑 config.yml, 然后重启服务器. + distance: "确保您已设定过岛屿距离. 若要升级, 请设为原值." + generator: |- + 岛屿世界生成器注册失败. + 可能的潜在原因: + 1. 若您将岛屿世界作为服务器的唯一世界 + 确保您已将此世界添加到 bukkit.yml 中. + 2. 您重载了服务器而并未重启. 请重启服务器重试. + generator-multiverse: " 3. 您的 Multiverse 插件已过期. 请升级到最新版本." + world-name: |- + config.yml 中的世界名与 islands.yml 中的世界名不符. + 若您这样做是有目的的, 系统将假设您想完全重设岛屿世界. + 若是, 请删除 islands.yml 和原世界. + 若否, 请修正 config.yml 中的世界名并重启. 若您正在升级, 您很可能是这种情况. + config-outdated: |- + config.yml 似乎已过期. + 请核实您的配置文件是否经过更新. + 若此错误持续出现, 您很可能是编辑了旧的配置文件, 而非新的配置文件. + 如果是这样, 请删除当前的 config.yml, 参照 config.new.yml 创建一个新的 config.yml. + +general: + success: "成功!" + errors: + no-permission: "您无权执行此命令." + use-in-game: "本命令仅在游戏中有效." + +# TODO: These are legacy strings and should be converted to a better format but will do for now +acidBottle: "受到辐射的水瓶" +acidBucket: "污染的水桶" +acidLore: |- + 小心! 小心! 小心! + 重要的事情说三遍! + 千万不能喝! + +adminDeleteIsland: + error: "使用 &ldeleteisland confirm &r&c来删除你所在的岛屿." + noid: "无法识别岛屿." + use: "或者使用 &ldelete [name] &r&c来删除一个玩家." +adminHelp: + add: "向领导者的队伍增加玩家" + addrange: "增加或减少岛屿的保护区域大小." + clearreset: "重置一个玩家的岛屿初始化次数." + clearresetall: "为所有玩家重置岛屿的初始化次数." + cobblestats: "显示magic cobble的生成统计数据." + completeChallenge: "标记一个挑战为已完成" + delete: "删除一个玩家的岛屿 (移除方块)." + help: "管理员指令:" + info: "显示指定玩家信息." + infoisland: "显示离你最近的岛屿信息." + kick: "从任何队伍中踢出玩家." + level: "为玩家提供岛屿等级详情." + listChallengeResets: "列出挑战重置时间表(若有)" + lock: "锁定或解锁玩家的岛屿." + purge: "删除超过 [TimeInDays] 天的不活跃岛屿." + purgeallowdisallow: "允许/禁止一个岛屿被删除(若它们达到删除标准)." + purgeholes: "重置空余的岛屿,以便重复使用." + purgeunowned: "移除无主岛屿." + name: "为玩家岛屿命名." + register: "设置玩家的岛屿在你的位置" + reload: "配置重读." + resetAllChallenges: "重置该玩家的的所有挑战" + resetChallenge: "标记一个挑战为未完成" + resetChallengeForAll: "重设全服务器每位玩家的挑战(可选重复)" + resetname: "重设玩家岛屿名称" + resetsign: "将你盯着看的牌子重设给岛主" + setbiome: "设置领导者岛屿的生物群系." + setdeaths: "设置玩家的死亡计数." + setrange: "改变岛屿的保护范围." + setlanguage: "设定默认语言并应用于所有玩家." + setspawn: "设置岛屿世界的重生点在你的附近." + settingsreset: "重设所有岛屿到默认保护设定" + teamChatSpy: "偷听岛屿team聊天(开启/关闭)" + topTen: "手动更新前十列表" + topbreeders: "列出目前载入的最活跃的岛屿" + tp: "传送到玩家岛屿" + tpnether: "传送到玩家的下界岛屿" + unregister: "删除一个玩家的岛屿信息,但不清除岛屿内方块" +adminInfo: + bannedPlayers: "已被封禁的玩家" + errorNullTeamLeader: "团队领导必须为空!" + errorTeamMembersExist: "玩家拥有团队成员,但不应该!" + hoppers: "岛上有 [number] 个漏斗" + islandLocation: "岛屿坐标" + isLocked: "岛屿被锁定" + isProtected: "岛屿被保护免于清除" + isSpawn: "岛屿是出生地" + isUnlocked: "岛屿被解锁" + isUnprotected: "岛屿未被保护免于清除" + lastLogin: "最后登录" + maxSize: "岛屿最大大小(距离)" + player: "玩家" + teamLeader: "队伍领袖" + teamMembers: "队伍成员" + title: "这是出生地岛屿" + unowned: "本岛暂时无主." +adminLock: + adminLockedIsland: "管理员锁定了你的岛屿" + adminUnlockedIsland: "管理员解锁了你的岛屿" + errorInGame: "必须在游戏内使用该命令!" +adminRegister: + hadIsland: "[name] 在 [location] 处拥有一个岛屿" + leadsTeam: "[name] 拥有一个队伍. 请先踢光队里的人." + noIsland: "本区域内无已知空岛!" + notSpawn: "你不能占领出生地!" + taking: "正从 [name] 玩家接管岛屿" +adminResetChallengeForAll: + error: "重复次数的格式必须是整数 [integer number][m/h/d] (minutes, hours, days), 例如. 5h" + repeating: "重复 [duration]" + reset: "重设 [date]" +adminResetSign: + errorExists: "传送牌已被激活过并属于 [name]" + found: "发现传送牌!" + noSign: "在执行此命令时你必须盯着传送牌杆看." + rescued: "已拯救传送牌并指派给 [name]" +adminReserve: + islandExists: "此地已有一岛屿! Register the player instead!" +adminSetHome: + homeSet: "已设家于 [location]" + noneFound: "未发现安全位置!" + notOnPlayersIsland: "你不在玩家岛屿上" + notSafe: "这位置不安全" +adminSetRange: + invalid: "范围无效!" + set: "设定新范围为 [number]" + tip: "范围必须在 10 到 [max] 之间" + updated: "岛屿范围更新为 [number]" + warning: "警告 - 范围比岛屿范围 [max] 更大" + warning2: "重叠的岛屿将像出生地一样(无法被拥有)!" +adminSetSpawn: + center: "岛屿中心 [location]" + coords: "保护坐标从 [min] 到 [max]" + limits: "岛屿限制从 [min] 到 [max]" + locked: "出生地被锁定!" + move: "再走远点或解除所有者的注册." + ownedBy: "本岛空间由 [name] 拥有" + range: "保护区域大小 = [number]" + set: "设定岛屿出生点到你的位置." + setting: "设定岛屿出生点到你的位置 [location]." +adminTeam: + addLeaderNoIsland: "团队领袖没有自己的岛屿所以不能拥有队员!" + addLeaderToOwn: "无法让领袖再次加入同一团队." + addedLeader: "已向团队加入领袖!" + addingPlayer: "正向团队加入玩家." + alreadyOnTeam: "玩家已经属于本队!" + kickLeader: "该玩家是一名团队领袖. 先踢光队员. 使用 '/[label] info [name]' 来查找队员." + nowUnowned: "[name] 在 [location] 的岛屿现将成为无主之岛. 你可以手动删除它了." + settingHome: "设定玩家的家到领袖的家的位置" +adminTopBreeders: + checking: "正核对 [number] 个岛屿..." + finding: "正查找名列前茅的岛屿..." + nothing: "未发现生物." +adminTopTen: + finished: "已生成前十名单列表" + generating: "生成前十名单列表" +adminTp: + manualWarp: "未发现安全地点. 在 [location] 附近手动传送." +adminUnregister: + keepBlocks: "从世界中删除一个玩家, 但在 [location] 处仍保留原有空岛. " + onTeam: "玩家隶属于一个队伍——先把他赶出去." +ban: + alreadybanned: "[name] 早就被列入了黑名单!" + banned: "你被列入 [name] 的岛屿的黑名单!" + fail: "[name] 无法被列入黑名单!" + helpBan: "将一个玩家列入岛屿黑名单." + helpUnban: "将一个玩家从岛屿黑名单中移除" + helpBanList: "列出被封禁的玩家." + lifted: "被从 [name] 的岛屿黑名单中解除!" + liftedsuccess: "被 [name] 解除黑名单!" + none: "无" + notbanned: "[name] 未被列入黑名单!" + notteammember: "你无法将岛屿成员列入黑名单!" + notyourself: "你不能那样对自己做!" + success: "[name] 被岛屿列入黑名单!" +biome: + help: "打开生物群系界面." + paneltitle: "选择一个生物群系" + set: "岛屿生物群系设置为: [biome]!" + unknown: "未知生物群系!" + youbought: "购买花费: [cost]!" +boats: + warning: "现在离开船是一件危险的事情..." +challenges: + colors: "任务将根据不同难度显示不同颜色:" + complete: "已完成" + completeNotRepeatable: "已完成(不可重复)" + completeRepeatable: "已完成(可重复)" + completedtimes: "完成次数 [donetimes] / [maxtimes]" + errorIslandLevel: "你的岛屿等级必须达到 [level] 级才能够完成这个任务!" + errorItemsNotThere: "所有任务所需物品必须在你的岛上!" + errorNotCloseEnough: "任务所需物品必须在你 [number] 格范围内." + errorNotEnoughItems: "你没有足够的所需物品" + errorNotOnIsland: "你只能够在你的岛屿上那样做!" + errorRewardProblem: "奖励你物品的时候发生了未知错误,请联系管理员!" + erroryouaremissing: "未找到你的信息" + expReward: "经验奖励" + firstTimeRewards: "首次奖励" + guititle: "ASkyBlock 挑战" + help1: "输入 /c <挑战名字> 来查询一个挑战的信息." + help2: "输入 /c complete <挑战名字> 完成一个挑战." + incomplete: "未完成" + invalidChallengeName: "未知挑战名! 输入 /c help 获取更多信息" + itemTakeWarning: "当你完成挑战的时候所有挑战所需物品将会消失!" + level: "等级" + maxreached: "最大完成 [donetimes] / [maxtimes]" + moneyReward: "经济奖励" + name: "挑战名称" + nameHasCompleted: "恭喜玩家 [name] 完成了 [challenge] 挑战!" + navigation: "点击查看 [level] 级的挑战!" + notRepeatable: "这个挑战不可重复!" + repeatRewards: "重复奖励" + rewards: 奖励 + toComplete: "请至少再完成 [challengesToDo] 个等级为 [thisLevel] 的挑战来解锁当前等级挑战!" + toCompleteUse: "完成这个挑战,输入" + unknownChallenge: "未知挑战名 (请检查拼写)!" + youHaveCompleted: "你完成了 [challenge] 挑战!" + youHaveNotUnlocked: "你还没有解锁当前挑战!" + youRepeated: "你重复完成了 [challenge] 挑战!" +changingObsidiantoLava: "成功将黑曜石变为岩浆,请当心!" +checkteam: + checkingTeam: "检查 [name] 的团队" +completechallenge: + challangeCompleted: "[挑战系统]: [name] 完成了 [challengename] " + errorChallengeDoesNotExist: "挑战不存在或者已经完成" +confirm: + errorTimeLimitExpired: "超时,请重新运行指令." +coop: + cannotcoop: "只有岛屿领袖才能赋予其他玩家岛屿完全访问权限." + help: "暂时允许玩家完全访问你的岛屿" + invited: "[name] 囚禁了 [player] !" + listcoops: "列出协作的玩家" + madeyoucoopy: "[name] 把你囚禁了,直到你下线或者他们驱逐你." + notincoop: "[name] 未在你的团队中!" + onyourteam: "玩家早就在你的团队中了!" + removed: "[name] 取消了你的锁定状态!" + removesuccess: "[name] 不再是一个囚禁玩家." + success: "[name] 现在被你囚禁了,直到他们下线或者你驱逐他们." + uncoop: "移除玩家对您岛屿的完全访问" + useexpel: "输入 /expel 移除." +deaths: + deaths: "死亡次数" + died: "死了!" + leveldeaths: "&c[[number] 死]" +delete: + removing: "移除了 [name] 的岛屿." +drankAcid: "饮用辐射水源." +drankAcidAndDied: "饮用受到辐射的水而死亡." +error: + blockedbyapi: "此行为被某个使用API的插件阻止." + commandNotReady: "你现在不能使用此命令." + maxIslands: "已达到世界最大容许岛屿数! 请稍后再试!" + noIsland: "你还没有获得一个岛屿!" + noIslandOther: "玩家未拥有岛屿!" + noPermission: "你没有权限那样做!" + notABlock: "这不是一个方块" + noTeam: "玩家不再团队中." + notOnIsland: "你必须在你的岛屿上使用这个指令." + offlinePlayer: "玩家不在线或不存在." + tooLong: "太长. 最大长度为 [length]." + tooShort: "太短. 最小长度为 [length]." + unknownCommand: "未知指令." + unknownPlayer: "未知玩家." + useInGame: "这个指令必须在游戏内使用." + wrongWorld: "你无法在当前世界这样操作,请返回你的岛屿." + minishopDisabled: "迷你商店未启用." +expel: + expelled: "你被驱逐出了岛屿!" + fail: "[name] 无法被驱逐!" + notonisland: "玩家没有入侵你的岛屿!" + notyourself: "你无法驱逐你自己!" + success: "你驱逐了玩家: [name]!" +invite: + errorCantJoinIsland: "你不能加入这个岛屿, 可能岛屿已满员." + errorCoolDown: "你需要等待 [time] 分钟后才能再次邀请那个玩家" + errorThatPlayerIsAlreadyInATeam: "这个玩家已经被被其他岛屿邀请了, 或者已经拥有自己的岛屿." + errorYouCannotInviteYourself: "你不能邀请你自己入住!" + errorYouMustHaveIslandToInvite: "你必须拥有一个岛屿, 才能邀请其他玩家入住!" + errorYourIslandIsFull: "你的岛屿住满了人, 你没办法再邀请其他玩家了." + hasJoinedYourIsland: "[name] 加入了你的岛屿!" + help: "输入/[label] invite <玩家ID> 邀请玩家加入你的岛屿." + inviteSentTo: "邀请已发送给 [name]" + nameHasInvitedYou: "[name] 邀请你入住他的岛屿!" + onlyIslandOwnerCanInvite: "只有岛屿主人才能邀请其他玩家!" + removingInvite: "移除了你之前邀请的玩家." + toAcceptOrReject: "来接受或拒绝岛屿入住邀请." + warningYouWillLoseIsland: "警告: 如果你接受, 你将失去当前这个岛屿!" + youCanInvite: "你还能邀请 [number] 个玩家." + youCannotInvite: "你无法邀请更多的玩家了." + youHaveJoinedAnIsland: "你加入了一个岛屿! 使用 /[label] team 来查看其他成员." +island: + blockValue: "置于此处的 [name] 可能价值[value]" + blockWorthless: "[name] 一毛不值" + cannotTeleport: "你无法在下落过程中进行传送!" + donate: "本插件由tastybento提供" + donatecolor: "aqua" + error: + CouldNotCreateIsland: "无法为你创建岛屿. 请联系管理员." + InvalidPlayer: "玩家不存在或者他不曾拥有一个岛屿!" + LevelNotReady: "请稍等数秒后再输入此指令!" + YouDoNotHavePermission: "你没有权限那样做!" + YouAlreadyHaveAnIsland: "你已经有一个岛屿了!" + help: + AcceptReject: "接受或者拒绝别人的邀请." + Challenges: "输入指令/challenges: &7显示挑战任务" + Color: "&e" + ControlPanel: "打开岛屿帮助界面." + Expel: "强制从你的岛屿上请走一个玩家." + Invite: "邀请玩家加入你的岛屿." + Island: "开始岛屿生涯,或者回到你的岛屿." + IslandSpawn: "回到岛屿出生点." + Kick: "将玩家从你的岛屿移除." + Leave: "离开了当前岛屿." + Level: "计算你的岛屿等级" + LevelPlayer: "查询玩家的岛屿等级." + Lock: "岛屿已锁定, 非岛屿成员无法传送至岛屿上" + MakeLeader: "将岛屿赠送给玩家." + Name: "给你的岛屿起个名" + ResetName: "重置你的岛屿名称." + Restart: "重新开始你的岛屿生涯." + SelectLanguage: "语言选择(Select Language)" + SetHome: "设置返回岛屿的传送坐标(需要在自己岛屿内设置)." + Settings: "查看岛屿保护和游戏设置" + Team: "显示你团队的信息." + Teleport: "传送到你的岛屿." + Top: "查询岛屿等级排行榜." + Value: "查看手中方块的岛屿价值" + Warp: "传送到玩家的传送点." + Warps: "列出所有可用的传送点." + islandDeletedLifeboats: "岛屿已删除! 火速前往救生船!" + islandLevelis: "岛屿等级为" + new: "正在为你创建一个新的岛屿..." + requiredPointsToNextLevel: "你还需要 [points] 点数来达到 [next] 级!" + reset: + Confirm: "请在 [seconds] 秒内输入/[label] confirm 来确认你的操作,然后重新开始!" + MustRemovePlayers: "你只有将岛屿所有成员踢出才能重新开始 (/[label] kick <玩家ID>). 输入/[label] team 可以查询成员列表." + NoMore: "你无法再重新开始了!" + OnlyOwner: "只有岛屿的主人才能那样做. 请输入/[label] leave离开当前团队,然后重新你的岛屿生涯." + PleaseWait: "请稍等, 正在创建新的岛屿..." + Left: "重设剩余次数" + To: "清除重新开始限制" + Wait: "你需要等待 [time] 秒才能那样做." + YouHave: "你还有 [number] 次重新开始的机会." + subtitle: "by tastybento" + subtitlecolor: "blue" + teleport: "[岛屿娘]:欢饮回来~我的主人. (输入/[label] help 获取更多帮助)" + title: "BSkyBlock" + titlecolor: "gold" + unlimited: "无限" + url: "" +islandProtected: "岛屿保护." +islandguardsettings: + TNTdamage: "是否开启TNT爆炸伤害" + allowed: "允许" + aciddamage: "酸雨伤害" + animalspawning: "允许/禁止动物出生" + anvil: "是否允许使用铁毡" + armorstand: "是否允许使用盔甲架" + beacon: "是否允许使用信标" + bed: "是否允许使用床" + breakblocks: "是否允许破坏" + breeding: "是否允许喂养" + brewingstand: "是否允许酿造药水" + bucket: "是否允许使用桶" + collectlava: "是否允许收集岩浆" + collectwater: "是否允许收集水" + chest: "是否允许使用箱子" + chestdamage: "TNT能否破坏箱子" + chorusfruit: "是否允许使用紫颂果" + creeperdamage: "苦力怕伤害" + creepergriefing: "苦力怕破坏" + creeperpain: "苦力怕爆炸伤害" + croptrample: "是否允许践踏农作物" + disallowed: "不允许" + door: "是否允许使用门" + eggs: "是否允许扔鸡蛋" + enchantingtable: "是否允许使用附魔台" + enderpearl: "是否允许使用末影珍珠" + fire: "是否允许使用打火石" + fireextinguish: "熄灭火焰" + firespread: "火焰传播" + furnace: "是否允许使用熔炉" + gate: "是否允许使用栅栏门" + horseinventoryaccess: "是否允许参观者查看马的物品栏" + horseriding: "是否允许参观者骑马" + hurtanimals: "是否允许攻击动物" + hurtmonsters: "是否允许攻击怪物" + joinleaveislandmessages: "启用岛屿进入与离开消息" + jukebox: "是否允许使用唱片机" + leash: "是否允许使用栓绳" + lever: "是否允许使用开关按钮" + milking: "挤奶" + monsterspawning: "允许/禁止岛屿刷怪" + netherpvp: "是否允许地狱PVP" + placeblocks: "是否允许放置方块" + portaluse: "是否允许使用传送门" + pressureplate: "是否允许参观者激活压力盘" + pvp: "是否允许PVP" + redstone: "是否允许使用红石" + settingsgeneraltitle: "一般岛屿世界设定" + settingsgeneraldesc: "一般岛屿世界设定" + settingsislandtitle: "岛屿设定" + settingsislanddesc: "这些规则适用于岛屿的参观者" + settingsspawntitle: "出生地设定" + settingsspawndesc: "这些规则适用于出生地" + shears: "是否允许使用剪刀" + spawnegg: "是否允许使用刷怪蛋" + teleportwhenfalling: "下落时是否允许传送" + title: "岛屿保护设置" + villagertrading: "是否允许村民交易" + visitordrop: "是否允许访问者掉落物品" + visitorkeepitems: "访问者死亡是否保存背包" + visitorpickup: "是否允许访问者捡起物品" + withergriefing: "是否开启凋零破坏" + workbench: "是否允许使用合成台" +kick: + errorNoTeam: "你没有加入任何岛屿的团队!" + errorNotPartOfTeam: "这个玩家不是你的岛屿成员之一!" + errorOnlyLeaderCan: "只有岛屿主人才能踢人!" + errorPlayerNotInTeam: "这个玩家不在你的岛屿团队中!" + nameRemoved: "[name] 刚才已被驱逐出岛." + nameRemovedYou: "[name] 将你驱逐出了他的岛屿!" +lavaTip: "温馨提示: 如果岩浆变成了黑曜石,可以使用铁桶右键变回岩浆." +leave: + canceled: "离开已取消." + errorLeadersCannotLeave: "空岛主人无法离开岛屿.请输入 /[label] makeleader <玩家ID> 来转让岛屿." + errorYouAreTheLeader: "因为你是岛屿主人所以不能离开, 使用 /[label] makeleader <玩家> 来改变岛屿主人." + errorYouCannotLeaveIsland: "你无法离开岛屿当只剩下你一个人的时候.如果你想重新开始, 请输入 /[label] restart!" + errorYouMustBeInWorld: "你只能在岛屿世界离开你的队伍!" + nameHasLeftYourIsland: "[name] 离开了你的岛屿!" + warning: "你确定要离开队伍吗? 再次键入 '/[label] leave' 以确认." + youHaveLeftTheIsland: "你离开了岛屿, 并返回到了玩家出生地." +level: + calculating: "正在计算岛屿等级, 需要等待一段时间. 请稍候..." + errornotYourIsland: "只有岛屿成员才能使用." + islandLevel: "岛屿等级" +lock: + enteringspawn: "进入出生点" + islandlocked: "岛屿禁止游客访问" + leavingspawn: "离开出生点" + locking: "锁定岛屿" + nowentering: "您所访问的是 [name] 的岛屿" + nowleaving: "你已经离开了 [name] 的岛屿" + unlocking: "解锁岛屿" +makeleader: + errorGeneralError: "不能改变岛屿主人." + errorNotYourIsland: "这不是你的岛屿, 所以你没有权限!" + errorPlayerMustBeOnline: "玩家只有在线才能接受你的岛屿." + errorRemoveAllPlayersFirst: "将所有玩家踢出团队, 才能进行团队转让." + errorThatPlayerIsNotInTeam: "这个玩家不是你的岛屿成员之一!" + errorYouMustBeInTeam: "你必须在一个团队中才能转让岛屿." + nameIsNowTheOwner: "[name] 现在是你的岛屿主人了!" + youAreNowTheOwner: "你现在是岛屿主人了." +minishop: + buy: "购买" + buyproblem: "购买出错" + islandhelpMiniShop: "打开迷你商店" + outofstock: "物品卖完了哟" + sell: "出售" + sellproblem: "你没有足够的物品." + title: "迷你商店-左键购买右键出售" + youbought: "你购买了 [number] 个[description], 花费了 [price]" + youcannotafford: "余额不足!" + yousold: "你出售了 [number] 个 [description], 获得了 [price]" +moblimits: + entity: "岛屿实体 [entity] 的数量达到极限([number])!" + error: "岛屿繁殖数量 [number] 达到极限!" + hopper: "岛屿漏斗放置数量 [number] 达到极限!" + villager: "岛屿村民繁殖数量 [number] 达到极限!" +nether: + spawnisprotected: "当前位置为地狱保护区,请勿破坏." +news: + headline: "[岛屿快讯]: 你离线的时候发生了..." +purge: + acidFound: "已有 [number] 个无主岛屿. 使用 '/acid purge unowned confirm' 来在20s内删除它们." + allowPurge: "清除保护已移除" + alreadyRunning: "正在清理中, 请等待清理完毕!" + calculating: "计算不活跃天数超过 [time] 天的岛屿." + countingUnowned: "正在计数无主岛屿并检查玩家文件. 可能会花一点时间..." + maxPurge: "一次最大清理数为 [number] 个岛屿. 再次运行purge命令以清理更多." + finished: "清理不活跃岛屿完成." + noneFound: "没有不活跃的岛屿被移除." + nowWaiting: "请等待..." + preventPurge: "岛屿是免受清除的" + purgeCancelled: "取消清理." + removingAt: "正删除位于 [location] 的岛屿" + removingName: "清理: 移除了 [name] 的岛屿" + skyblockFound: "还有 [number] 个无主岛屿. 使用 '/asadmin purge unowned confirm' 来在20s内删除它们." + stillChecking: "仍在检查玩家文件..." + thisWillRemove: "这将会移除 [number] 个不活跃的岛屿!" + typeConfirm: "请在10秒内输入 /[label] confirm 进行确定" + usage: "使用方式: /[label] purge [TimeInDays]" + warning: "危险! 当服务器内还有玩家的时候请不要运行这个命令! 请将你的服务器进行备份!!!" +register: + errorBedrockNotFound: "基岩未找到: 无法设置岛屿!" + settingIsland: "设置 [name] 岛屿的基岩在你当前位置." +reject: + nameHasRejectedInvite: "[name] 拒绝了你的岛屿入驻邀请!" + youHaveNotBeenInvited: "你没有收到任何岛屿入住邀请." + youHaveRejectedInvitation: "你拒绝了岛屿入住邀请." +reload: + configReloaded: "配置重读." +resetallchallenges: + success: "[name] 的所有挑战已经重置." +resetchallenge: + challengeReset: "[挑战系统]: [name] 的挑战: [challengename] 已经重置" + errorChallengeDoesNotExist: "挑战不存在或尚未完成" +schematics: + title: "请选择你想要的岛屿..." +sethome: + errorNoIsland: "你不是岛屿的一员. 请返回你的岛屿!" + errorNotOnIsland: "你只能在你的岛屿范围内设置!" + errorNumHomes: "家只能设置 1-[max] 个" + homeSet: "已经设置家在你当前位置." +settingsReset: + done: "完成." + inprogress: "重设保护设置中, 请稍待..." +sign: + line1: "&1[末日岛屿]" + line2: "[player]" + line3: "不要掉下去!" + line4: "努力活下去!" +sign-acidisland: + line1: "&1[酸雨岛&7]" + line2: "[player]" + line3: "水有酸性!" + line4: "千万小心!" +targetInPVPArea: "目标处于禁止PVP区域!" +team: + listingMembers: "显示你岛屿的成员" +teamchat: + helpChat: "开启/关闭团队聊天" + noTeam: "你不在一个团队中!" + noTeamAround: "没有团队成员在线!" + prefix: "[团队聊天]<{ISLAND_PLAYER}> " + spyoff: "关闭团队聊天窃听" + spyon: "打开团队聊天窃听" + statusOff: "团队聊天已经关闭" + statusOn: "团队聊天已经开启" +topTen: + errorExcluded: "仅供参考: 你被逐出了前十名, 因为你没有 [perm]" + errorNotReady: "前十名单尚未生成!" + guiHeading: "&E&L 岛屿: &6&N[name]&7 (#[rank])" + guiTitle: "前10岛屿" + header: "排名前10的岛屿:" +warps: + deactivate: "旧的传送点被替换!" + errorDoesNotExist: "传送点不存在!" + errorDuplicate: "当前位置已经存在传送点!" + errorNoPerm: "你没有权限创建岛屿传送点!" + errorNoPlace: "你只能够在你的岛屿上创建传送点!" + errorNoRemove: "你只能移除你自己的传送点!" + errorNoWarpsYet: "没有任何传送点!" + errorNotReadyYet: "传送点未准备好.请稍后再试." + errorNotSafe: "传送点不安全.请稍后再试." + errorNotEnoughLevel: "你的岛屿等级不够, 无法创建欢迎牌!" + next: "下一页" + playerWarped: "[name] &e传送到了你的岛屿!" + previous: "上一页" + removed: "传送点已经移除!" + signRemoved: "你的岛屿传送点已经移除!" + success: "空岛传送点成功创建!" + title: "岛屿传送点" + warpTip: "放置一个木牌,并且在木牌的第一行输入“[WELCOME]”以设置一个岛屿传送点." + warpToPlayersSign: "传送到玩家: 的岛屿传送点." + warpsAvailable: "以下的传送点可用" + welcomeLine: "[WELCOME]" + From bdf8ecdce40b44c8a4d8f1618cae3a869c07e801 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 14 Jul 2017 15:03:14 +0900 Subject: [PATCH 2/4] Protection, database and license (#3) * Added more database functions. Added ability to check if a uniqueId exists without creating it - used to check if a player is known or not. Added join/quit listener. * Hooked in grid database to track where islands are. Added Nether events and portal function. Added default /island command operation. * Added protection for islands. * Updated license to BSD license. * Removed unused imports. Added configs. * Added more protection listeners. Flying mobs, visitor protection --- LICENSE | 361 +-- config.yml | 27 +- locales/bsb_en_US.yml | 21 +- schematics/double.schematic | Bin 1179 -> 0 bytes .../us/tastybento/bskyblock/BSkyBlock.java | 78 +- .../bskyblock/commands/AdminCommand.java | 2 - .../bskyblock/commands/IslandCommand.java | 235 +- .../tastybento/bskyblock/config/NotSetup.java | 2 +- .../bskyblock/config/PluginConfig.java | 56 +- .../tastybento/bskyblock/config/Settings.java | 24 +- .../bskyblock/config/YamlResourceBundle.java | 9 +- .../bskyblock/database/DatabaseConnecter.java | 9 + .../flatfile/FlatFileDatabaseConnecter.java | 6 + .../flatfile/FlatFileDatabaseHandler.java | 5 + .../managers/AbstractDatabaseHandler.java | 8 +- .../database/managers/IslandsManager.java | 356 ++- .../database/managers/PlayersManager.java | 80 +- .../mysql/MySQLDatabaseConnecter.java | 6 + .../database/mysql/MySQLDatabaseHandler.java | 30 +- .../bskyblock/database/objects/Island.java | 103 +- .../bskyblock/database/objects/Players.java | 1 + .../generators/ChunkGeneratorWorld.java | 19 +- .../bskyblock/generators/IslandWorld.java | 12 +- .../bskyblock/generators/NetherPopulator.java | 17 - .../listeners/JoinLeaveListener.java | 95 + .../bskyblock/listeners/NetherPortals.java | 256 ++ .../listeners/protection/FlyingMobEvents.java | 219 ++ .../listeners/protection/InventorySave.java | 66 + .../listeners/protection/InventoryStore.java | 52 + .../listeners/protection/IslandGuard.java | 2663 +++++++++++++++++ .../listeners/protection/IslandGuard1_8.java | 213 ++ .../listeners/protection/IslandGuard1_9.java | 498 +++ .../listeners/protection/NetherEvents.java | 232 ++ .../listeners/protection/VisitorGuard.java | 189 ++ .../bskyblock/schematics/BannerBlock.java | 17 - .../bskyblock/schematics/EntityObject.java | 17 - .../bskyblock/schematics/IslandBlock.java | 38 - .../bskyblock/schematics/PotBlock.java | 139 - .../bskyblock/schematics/Schematic.java | 30 +- .../bskyblock/schematics/SchematicsMgr.java | 2 +- .../bskyblock/schematics/SkullBlock.java | 308 -- .../bskyblock/util/DeleteIslandBlocks.java | 20 +- .../bskyblock/util/SafeSpotTeleport.java | 17 - .../us/tastybento/bskyblock/util/Util.java | 140 + .../bskyblock/util/VaultHelper.java | 6 +- .../bskyblock/util/nms/NMSAbstraction.java | 17 - 46 files changed, 5473 insertions(+), 1228 deletions(-) delete mode 100644 schematics/double.schematic create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/InventorySave.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/InventoryStore.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_8.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_9.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/NetherEvents.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/protection/VisitorGuard.java delete mode 100644 src/main/java/us/tastybento/bskyblock/schematics/PotBlock.java delete mode 100644 src/main/java/us/tastybento/bskyblock/schematics/SkullBlock.java diff --git a/LICENSE b/LICENSE index 22fbe5dba..79ec189f5 100755 --- a/LICENSE +++ b/LICENSE @@ -1,339 +1,28 @@ -GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 +Copyright (c) 2017 tastybento, Poslovitch +All rights reserved. - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - Preamble + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the BSkyBlock team nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. \ No newline at end of file +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/config.yml b/config.yml index 6d30c5b57..37375f65b 100644 --- a/config.yml +++ b/config.yml @@ -48,11 +48,12 @@ general: ### Database-related Settings ### database: - # FLATFILE, MYSQL, SQLITE + # FLATFILE, MYSQL type: FLATFILE - - mysql: 0 #TODO - sqlite: 0 #TODO + port: 3306 + name: BSkyBlock + username: username + password: password # How often the data will be saved to file in mins. Default is 5 minutes. # This helps prevent issues if the server crashes. @@ -95,18 +96,16 @@ general: world: # Name of the world - if it does not exist then it will be generated. # It acts like a prefix for nether and end (e.g. BSkyBlock, BSkyBlock_nether, BSkyBlock_end) - world-name: BSkyBlock + world-name: BSkyBlock_world - # Distance between islands in blocks - NEVER change this mid-game. + # Distance between islands in blocks IN CHUNKS (1 chunk = 16 blocks) # It is the same for every dimension : Overworld, Nether and End. - # Values for a new world: - # 400 - puts players distance enough that they usually cannot see each other - # 200 - allows some expansion of the protected zone (recommended) - # 110 - for compatibility with established worlds. Cozy. - # 50 - minimum - not recommended - # IF YOU ARE UPGRADING YOU MUST USE YOUR OLD VALUE EXACTLY (E.G.: 110), OR RESET YOUR WORLD - # Value must be an even number (must end with 0, 2, 4, 6, 8) - distance: 200 + # Recommended values for a new world: + # 24 - puts players distance enough that they usually cannot see each other + # 12 - allows some expansion of the protected zone (recommended) + # 4 - minimum - not recommended + # IF YOU ARE UPGRADING YOU MUST USE YOUR OLD VALUE EXACTLY (E.G.: 24), OR RESET YOUR WORLD + distance-in-chunks: 24 # Default protection range (even number). Min = 0, Recommended = 100 # Larger values will take longer to calculate the island level diff --git a/locales/bsb_en_US.yml b/locales/bsb_en_US.yml index 6c02428a6..d1296f016 100755 --- a/locales/bsb_en_US.yml +++ b/locales/bsb_en_US.yml @@ -342,6 +342,7 @@ island: islandDeletedLifeboats: "Island deleted! Head to the lifeboats!" islandLevelis: "Island level is" new: "Creating a new island for you..." + protected: "Island protected." requiredPointsToNextLevel: "You need [points] more points to reach level [next]!" reset: Confirm: "Type /[label] confirm within [seconds] seconds to delete your island and restart!" @@ -360,7 +361,6 @@ island: titlecolor: "gold" unlimited: "Unlimited" url: "" -islandProtected: "Island protected." islandguardsettings: TNTdamage: "TNT Damage" allowed: "Allowed" @@ -557,15 +557,16 @@ topTen: header: "These are the Top 10 islands:" warps: deactivate: "Deactivating old sign!" - errorDoesNotExist: "That warp doesn't exist!" - errorDuplicate: "Sorry! There is a sign already in that location!" - errorNoPerm: "You do not have permission to place Welcome Signs yet!" - errorNoPlace: "You must be on your island to place a Welcome Sign!" - errorNoRemove: "You can only remove your own Welcome Sign!" - errorNoWarpsYet: "There are no warps available yet!" - errorNotReadyYet: "That warp is not ready yet. Try again later." - errorNotSafe: "That warp is not safe right now. Try again later." - errorNotEnoughLevel: "You do not have enough island levels to create a Welcome Sign!" + error: + DoesNotExist: "That warp doesn't exist!" + Duplicate: "Sorry! There is a sign already in that location!" + NoPerm: "You do not have permission to place Welcome Signs yet!" + NoPlace: "You must be on your island to place a Welcome Sign!" + NoRemove: "You can only remove your own Welcome Sign!" + NoWarpsYet: "There are no warps available yet!" + NotReadyYet: "That warp is not ready yet. Try again later." + NotSafe: "That warp is not safe right now. Try again later." + NotEnoughLevel: "You do not have enough island levels to create a Welcome Sign!" next: "Next" playerWarped: "[name] &2warped to your island!" previous: "Previous" diff --git a/schematics/double.schematic b/schematics/double.schematic deleted file mode 100644 index 0dce3e5a2cdbbfc9fc0ec643357dc7b2a1a04a05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1179 zcmV;M1Z4XkiwFP!000000PWqqZ`(!~$MHMTdZ9r9mb$Qul_}{I6dgJ=>5w=nS|CMH z*hZQz1tHTGV_7OJ8fg1hckK({9w`}c#pj_dT8<^;`vDS}_wbJAAwQfbg|}^j{lPFf zi?ej#o8ay1AC8ZwN%qs_<>g<2X}=z4X_h9_ZR4~}@O_*m=V?5en#POKufy0g&2N+R zWSE)gTJLwR_n+5}e|E?J&W_L1lXU#f4fgcfaelRbT4w82oW;gmd~N^$0000000000 z008jd8V@}I0Jt|K8~^~o`r6V8zNb~JRtVa6oecog&|KL_YVcJ=9{@ZIbrH9j>MSF} zmCph|P0ByVP%l-Dvvik=%da=yK?5623z;yKE3R3ssADZZtwK<<9{|*~{tK_V{DtG2 z?+`W?yWE7EjsR|{MqF6q3B6`b9f8xMZ*L)m1>l&S<<799iA7@_;CX>_T=$FAT9h@d( z&op1fXYomrfA6HRH@O&Ro;6$hqe*sk+157~=i_*gc&7c*{dAC?CHd0`I(u%Q{NP}c z#iRV>|Ih2GJOApGqA{Q3_I#3`xB;4PlJQA4G+%h8@iskjKYiLV&6guL$dp}W0RR91 z00000*lhfNR{$GtS1V`t&o3(F@$%*%lv3249t4qa$E~P{K{o3mWkM*&=)JJkS062E#XE?;+Qqdm`Iu4` zcfe{0@z*tv^sRRG)xg}B3Pqc^APc_^g?KG0RS74r?u^oWBRxs9RI=Ja(&`U;H(Hk` z!ZYJ@yKDV69oT5ydfoQbin^Uo^hiEm3o>bCIj_{*GU!mPyw_G_pUFXHXMKc9$0&<6 zUtJLDE681<54e?{-mH}5=<8LDR(%a2mWpvgeS60hZ+>=Ib-zunyw4YL(sn)WPfM(5 zi#XqE3&M_m$C1??a5q|5^?Gup*Xybkb*$y5Rrs-HKkb%&9#+0k^!>cu_n$Acdv;zZ zRs7jd{`18`eiyFjQM!m%G)sGud9IJPR~dj0tZrVdo)!yYj1|q+^Gc!Q3ZB>TT;<5{8N&2*lX3PlI^moQt`>h-0GS!o|g03SIqE@ttgw4456DU@6xAL#I~TzG7{ zeOK$3D}B=!ukP9(7lVn#FXahqzX$-7^tHs0L#Z-gYJLy{03VuuZ&9hJHytZ_sCOd) t;69OX06s?Qr@&q9Yc}K randomSet = new HashSet(); - island.addMember(owner); - for (int i = 0; i < 10; i++) { - randomSet.add(UUID.randomUUID()); - island.addMember(UUID.randomUUID()); - island.addToBanList(UUID.randomUUID()); - } - island.setBanned(randomSet); - island.setCoops(randomSet); - island.setTrustees(randomSet); - island.setMembers(randomSet); - for (SettingsFlag flag: SettingsFlag.values()) { - island.setFlag(flag, true); - } - island.setLocked(true); - island.setName("new name"); - island.setPurgeProtected(true); - islandsManager.save(false); - - - getLogger().info("DEBUG: ************ Finished saving, now loading *************"); - - */ - - playersManager.load(); + // Load islands from database islandsManager.load(); // Load schematics @@ -153,6 +112,8 @@ public class BSkyBlock extends JavaPlugin{ Settings.defaultLanguage = "en-US"; loadLocales(); + // Register Listeners + registerListeners(); /* *DEBUG CODE Island loadedIsland = islandsManager.getIsland(owner); @@ -182,6 +143,17 @@ public class BSkyBlock extends JavaPlugin{ } } + protected void registerListeners() { + PluginManager manager = getServer().getPluginManager(); + // Player join events + manager.registerEvents(new JoinLeaveListener(this), this); + manager.registerEvents(new NetherEvents(this), this); + manager.registerEvents(new NetherPortals(this), this); + manager.registerEvents(new IslandGuard(this), this); + manager.registerEvents(new IslandGuard1_8(this), this); + manager.registerEvents(new IslandGuard1_9(this), this); + } + @Override public void onDisable(){ // Save data @@ -275,10 +247,10 @@ public class BSkyBlock extends JavaPlugin{ * @return the locale for this player */ public BSBLocale getLocale(UUID player){ - getLogger().info("DEBUG: " + player); - getLogger().info("DEBUG: " + getPlayers() == null ? "Players is null":"Players in not null"); - getLogger().info("DEBUG: " + getPlayers().getPlayer(player)); - getLogger().info("DEBUG: " + getPlayers().getPlayer(player).getLocale()); + //getLogger().info("DEBUG: " + player); + //getLogger().info("DEBUG: " + getPlayers() == null ? "Players is null":"Players in not null"); + //getLogger().info("DEBUG: " + getPlayers().getPlayer(player)); + //getLogger().info("DEBUG: " + getPlayers().getPlayer(player).getLocale()); String locale = getPlayers().getPlayer(player).getLocale(); if(locale.isEmpty() || !locales.containsKey(locale)) return locales.get(Settings.defaultLanguage); diff --git a/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java b/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java index baf8054dc..e07efe58b 100755 --- a/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java @@ -3,10 +3,8 @@ package us.tastybento.bskyblock.commands; import java.util.List; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.util.VaultHelper; public class AdminCommand extends BSBCommand{ diff --git a/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java b/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java index 97d20f115..800d69e6a 100755 --- a/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java @@ -46,7 +46,18 @@ public class IslandCommand extends BSBCommand{ @Override public void onExecuteDefault(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + if (sender instanceof Player) { + Player player = (Player)sender; + if (plugin.getIslands().hasIsland(player.getUniqueId())) { + // Has island + plugin.getIslands().homeTeleport(player); + } else { + // Create island + createIsland(player); + } + } else { + Util.sendMessage(sender, plugin.getLocale().get("general.errors.use-in-game")); + } } @Override @@ -62,7 +73,34 @@ public class IslandCommand extends BSBCommand{ @Override public void onExecute(CommandSender sender, String label, String[] args) { Util.sendMessage(sender, ChatColor.GOLD + "About " + ChatColor.GREEN + plugin.getDescription().getName() + ChatColor.GOLD + " v" + ChatColor.AQUA + plugin.getDescription().getVersion() + ChatColor.GOLD + ":"); - Util.sendMessage(sender, ChatColor.GOLD + "(c) 2014 - 2017 by Tastybento & Poslovitch"); + Util.sendMessage(sender, ChatColor.GOLD + "Copyright (c) 2017 tastybento, Poslovitch"); + Util.sendMessage(sender, ChatColor.GOLD + "All rights reserved."); + Util.sendMessage(sender, ChatColor.GOLD + ""); + Util.sendMessage(sender, ChatColor.GOLD + "Redistribution and use in source and binary forms, with or without"); + Util.sendMessage(sender, ChatColor.GOLD + "modification, are permitted provided that the following conditions are met:"); + + Util.sendMessage(sender, ChatColor.GOLD + " * Redistributions of source code must retain the above copyright notice,"); + Util.sendMessage(sender, ChatColor.GOLD + " this list of conditions and the following disclaimer."); + + Util.sendMessage(sender, ChatColor.GOLD + " * Redistributions in binary form must reproduce the above copyright"); + Util.sendMessage(sender, ChatColor.GOLD + " notice, this list of conditions and the following disclaimer in the"); + Util.sendMessage(sender, ChatColor.GOLD + " documentation and/or other materials provided with the distribution."); + + Util.sendMessage(sender, ChatColor.GOLD + " * Neither the name of the BSkyBlock team nor the names of its"); + Util.sendMessage(sender, ChatColor.GOLD + " contributors may be used to endorse or promote products derived from"); + Util.sendMessage(sender, ChatColor.GOLD + " this software without specific prior written permission."); + + Util.sendMessage(sender, ChatColor.GOLD + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\""); + Util.sendMessage(sender, ChatColor.GOLD + "AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"); + Util.sendMessage(sender, ChatColor.GOLD + "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"); + Util.sendMessage(sender, ChatColor.GOLD + "ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE"); + Util.sendMessage(sender, ChatColor.GOLD + "LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR"); + Util.sendMessage(sender, ChatColor.GOLD + "CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF"); + Util.sendMessage(sender, ChatColor.GOLD + "SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS"); + Util.sendMessage(sender, ChatColor.GOLD + "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN"); + Util.sendMessage(sender, ChatColor.GOLD + "CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)"); + Util.sendMessage(sender, ChatColor.GOLD + "ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE"); + Util.sendMessage(sender, ChatColor.GOLD + "POSSIBILITY OF SUCH DAMAGE. "); } @Override @@ -81,7 +119,7 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return true; } @@ -97,7 +135,7 @@ public class IslandCommand extends BSBCommand{ @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -114,13 +152,13 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @@ -140,7 +178,7 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return true; } @@ -149,8 +187,7 @@ public class IslandCommand extends BSBCommand{ if (sender instanceof Player) { Player player = (Player)sender; if (!plugin.getIslands().hasIsland(player.getUniqueId())) { - Schematic schematic = plugin.getSchematics().getSchematic("default"); - plugin.getIslands().newIsland(player, schematic); + createIsland(player); } else { Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player).get("island.error.YouAlreadyHaveAnIsland")); } @@ -159,7 +196,7 @@ public class IslandCommand extends BSBCommand{ @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -174,19 +211,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -201,19 +238,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -228,13 +265,13 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return true; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + if (!(sender instanceof Player)) { Util.sendMessage(sender, plugin.getLocale().get("error.useInGame")); } @@ -258,7 +295,7 @@ public class IslandCommand extends BSBCommand{ @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -273,19 +310,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -414,19 +451,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -441,19 +478,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -468,19 +505,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -495,19 +532,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -522,19 +559,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -549,19 +586,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -576,19 +613,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -603,19 +640,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -630,19 +667,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -657,19 +694,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -684,19 +721,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -711,19 +748,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -738,19 +775,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -765,19 +802,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -792,19 +829,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -819,19 +856,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -846,19 +883,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -873,19 +910,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -900,19 +937,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -927,19 +964,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -954,19 +991,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -981,19 +1018,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -1055,19 +1092,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -1082,19 +1119,19 @@ public class IslandCommand extends BSBCommand{ @Override public boolean canExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return false; } @Override public void onExecute(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + } @Override public List onTabComplete(CommandSender sender, String label, String[] args) { - // TODO Auto-generated method stub + return null; } @@ -1105,4 +1142,14 @@ public class IslandCommand extends BSBCommand{ }); } + /** + * Creates an island for player + * @param player + */ + protected void createIsland(Player player) { + //TODO: Add panels, make a selection. + Schematic schematic = plugin.getSchematics().getSchematic("default"); + plugin.getIslands().newIsland(player, schematic); + } + } diff --git a/src/main/java/us/tastybento/bskyblock/config/NotSetup.java b/src/main/java/us/tastybento/bskyblock/config/NotSetup.java index eb9fbe960..f086856ad 100644 --- a/src/main/java/us/tastybento/bskyblock/config/NotSetup.java +++ b/src/main/java/us/tastybento/bskyblock/config/NotSetup.java @@ -22,7 +22,7 @@ public class NotSetup implements CommandExecutor{ DIFFERENT_ISLAND_DISTANCE(0, 002), PROTECTION_RANGE_HIGHER_THAN_ISLAND_DISTANCE(1, 101), UNKNOWN_LANGUAGE(2, 201), - NOT_EVEN_ISLAND_DISTANCE(2, 202), + NOT_CHUNK_ISLAND_DISTANCE(2, 202), NOT_EVEN_PROTECTION_RANGE(2, 203), PURGE_ISLAND_LEVEL_TOO_LOW(3, 301), ISLAND_DISTANCE_TOO_LOW(3, 302), diff --git a/src/main/java/us/tastybento/bskyblock/config/PluginConfig.java b/src/main/java/us/tastybento/bskyblock/config/PluginConfig.java index eb8dcceab..3c54c7a8e 100755 --- a/src/main/java/us/tastybento/bskyblock/config/PluginConfig.java +++ b/src/main/java/us/tastybento/bskyblock/config/PluginConfig.java @@ -4,6 +4,8 @@ import java.util.HashMap; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.config.NotSetup.ConfigError; +import us.tastybento.bskyblock.database.BSBDatabase.DatabaseType; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; /** * Loads the plugin configuration and the locales. @@ -19,13 +21,8 @@ public class PluginConfig { * If there were errors, it setups the commands as "NotSetup" and generates a debug for admins to fix their configuration. * @return true if there wasn't any error, otherwise false. */ - public static boolean loadPluginConfig(BSkyBlock plugin){ - // Check if the config exists. It shouldn't happen, but the stack trace helps to know why. - try{ - plugin.getConfig(); - } catch (Exception exception){ - exception.printStackTrace(); - } + public static boolean loadPluginConfig(BSkyBlock plugin) { + plugin.saveDefaultConfig(); // Initialize the errors list HashMap errors = new HashMap(); @@ -51,7 +48,26 @@ public class PluginConfig { if(Settings.purgeMaxIslandLevel < 0) errors.put(ConfigError.PURGE_ISLAND_LEVEL_TOO_LOW, Settings.purgeMaxIslandLevel); Settings.purgeRemoveUserData = plugin.getConfig().getBoolean("general.purge.remove-user-data", false); - // TODO Database + // Database + String dbType = plugin.getConfig().getString("general.database.type","FLATFILE"); + boolean found = false; + for (DatabaseType type: DatabaseType.values()) { + if (type.name().equals(dbType.toUpperCase())) { + Settings.databaseType = type; + found = true; + break; + } + } + if (!found) { + plugin.getLogger().severe("Database type not found! Using FLATFILE"); + Settings.databaseType = DatabaseType.FLATFILE; + } + Settings.dbHost = plugin.getConfig().getString("general.database.host", "localhost"); + Settings.dbPort = plugin.getConfig().getInt("general.database.port",3306); + Settings.dbName = plugin.getConfig().getString("general.database.name", "BSkyBlock"); + Settings.dbUsername = plugin.getConfig().getString("general.database.username"); + Settings.dbPassword = plugin.getConfig().getString("general.database.password"); + Settings.recoverSuperFlat = plugin.getConfig().getBoolean("general.recover-super-flat", false); Settings.muteDeathMessages = plugin.getConfig().getBoolean("general.mute-death-messages", false); @@ -65,14 +81,14 @@ public class PluginConfig { Settings.acidBlockedCommands = plugin.getConfig().getStringList("general.allow-teleport.acid-blocked-commands"); // ********************* World ********************* - Settings.worldName = plugin.getConfig().getString("world.world-name", "BSkyBlock"); + Settings.worldName = plugin.getConfig().getString("world.world-name", "BSkyBlock_world"); //TODO check if it is the same than before - Settings.islandDistance = plugin.getConfig().getInt("world.distance", 200); - // TODO check if it is the same than before - if(Settings.islandDistance % 2 != 0) errors.put(ConfigError.NOT_EVEN_ISLAND_DISTANCE, Settings.islandDistance); - if(Settings.islandDistance < 50) errors.put(ConfigError.ISLAND_DISTANCE_TOO_LOW, Settings.islandDistance); - + int distance = plugin.getConfig().getInt("world.distance-in-chunks", 24); + // TODO this is an arbitrary number + Settings.islandDistance = distance * 16; + if(distance < 50) errors.put(ConfigError.ISLAND_DISTANCE_TOO_LOW, Settings.islandDistance); + Settings.islandProtectionRange = plugin.getConfig().getInt("world.protection-range", 100); if(Settings.islandProtectionRange % 2 != 0) errors.put(ConfigError.NOT_EVEN_PROTECTION_RANGE, Settings.islandProtectionRange); if(Settings.islandProtectionRange < 0) errors.put(ConfigError.PROTECTION_RANGE_TOO_LOW, Settings.islandProtectionRange); @@ -97,7 +113,17 @@ public class PluginConfig { if(Settings.netherSpawnRadius < 0) errors.put(ConfigError.NETHER_SPAWN_RADIUS_TOO_LOW, Settings.netherSpawnRadius); if(Settings.netherSpawnRadius > 100) errors.put(ConfigError.NETHER_SPAWN_RADIUS_TOO_HIGH, Settings.netherSpawnRadius); } - + // TODO: add to config + Settings.endGenerate = true; + Settings.endIslands = false; + Settings.limitedBlocks = new HashMap(); + Settings.defaultWorldSettings = new HashMap(); + for (SettingsFlag flag: SettingsFlag.values()) { + Settings.defaultWorldSettings.put(flag, false); + } + Settings.defaultWorldSettings.put(SettingsFlag.ANIMAL_SPAWN, true); + Settings.defaultWorldSettings.put(SettingsFlag.MONSTER_SPAWN, true); + // Entities //TODO end loading diff --git a/src/main/java/us/tastybento/bskyblock/config/Settings.java b/src/main/java/us/tastybento/bskyblock/config/Settings.java index 94a1b047d..04e0b89f0 100755 --- a/src/main/java/us/tastybento/bskyblock/config/Settings.java +++ b/src/main/java/us/tastybento/bskyblock/config/Settings.java @@ -11,6 +11,7 @@ import org.bukkit.potion.PotionEffectType; import us.tastybento.bskyblock.database.BSBDatabase.DatabaseType; import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages.HistoryMessageType; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; /** * All the plugin settings are here @@ -198,15 +199,11 @@ public class Settings { public static String dbUsername; public static String dbPassword; - public static boolean createNether; - public static boolean useOwnGenerator; - public static boolean islandNether; + public static boolean endGenerate; - public static boolean createEnd; - - public static boolean islandEnd; + public static boolean endIslands; public static boolean resetMoney; public static double acidDamage; public static int islandXOffset; @@ -214,4 +211,19 @@ public class Settings { public static int islandZOffset; public static int islandStartZ; + public static boolean logInRemoveMobs; + public static HashMap defaultWorldSettings; + public static boolean allowEndermanGriefing; + public static boolean endermanDeathDrop; + public static boolean allowTNTDamage; + public static boolean allowChestDamage; + public static boolean allowCreeperDamage; + public static boolean allowCreeperGriefing; + public static boolean allowAutoActivator; + public static boolean allowMobDamageToItemFrames; + public static HashMap limitedBlocks; + public static boolean allowTNTPushing; + public static boolean showInActionBar; + public static boolean allowVisitorKeepInvOnDeath; + } diff --git a/src/main/java/us/tastybento/bskyblock/config/YamlResourceBundle.java b/src/main/java/us/tastybento/bskyblock/config/YamlResourceBundle.java index facf6216e..5b27cff01 100644 --- a/src/main/java/us/tastybento/bskyblock/config/YamlResourceBundle.java +++ b/src/main/java/us/tastybento/bskyblock/config/YamlResourceBundle.java @@ -15,13 +15,15 @@ package us.tastybento.bskyblock.config; +import static java.util.Arrays.asList; +import static java.util.Collections.enumeration; +import static java.util.Collections.unmodifiableList; +import static java.util.stream.Collectors.toMap; + import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.AbstractMap.SimpleImmutableEntry; -import static java.util.Arrays.asList; -import static java.util.Collections.enumeration; -import static java.util.Collections.unmodifiableList; import java.util.Enumeration; import java.util.List; import java.util.Locale; @@ -30,7 +32,6 @@ import java.util.Map.Entry; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import static java.util.stream.Collectors.toMap; import java.util.stream.Stream; import org.yaml.snakeyaml.Yaml; diff --git a/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java b/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java index 1ce9d230e..0e1a8a858 100644 --- a/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java +++ b/src/main/java/us/tastybento/bskyblock/database/DatabaseConnecter.java @@ -33,6 +33,14 @@ public interface DatabaseConnecter { * @return a unique key for this record */ public String getUniqueId(String tableName); + + /** + * Check if a key exists in the database in this table or not + * @param simpleName + * @param key + * @return true if it exists + */ + public boolean uniqueIdExists(String simpleName, String key); /** * Loads a YAML file. Used by the flat file database @@ -49,5 +57,6 @@ public interface DatabaseConnecter { * @param fileName - the name of the record. Must be unique. */ public void saveYamlFile(YamlConfiguration yamlFile, String tableName, String fileName); + } diff --git a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseConnecter.java b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseConnecter.java index 900c5a8f7..4b96a6aff 100644 --- a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseConnecter.java +++ b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseConnecter.java @@ -111,4 +111,10 @@ public class FlatFileDatabaseConnecter implements DatabaseConnecter { return uuid.toString(); } + @Override + public boolean uniqueIdExists(String tableName, String key) { + File file = new File(dataFolder, tableName + File.separator + key + ".yml"); + return file.exists(); + } + } diff --git a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java index 6f8fa6029..59ace12d5 100644 --- a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java @@ -71,6 +71,11 @@ public class FlatFileDatabaseHandler extends AbstractDatabaseHandler { YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName(), key); return createObject(config); } + + @Override + public boolean objectExits(String key) { + return databaseConnecter.uniqueIdExists(type.getSimpleName(), key); + } /** * Loads all the records in this table and returns a list of them diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java index 0aa8fe398..97e373dba 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java @@ -8,7 +8,6 @@ import java.util.List; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.database.DatabaseConnecter; -import us.tastybento.bskyblock.database.objects.Island; /** * An abstract class that handles insert/select-operations into/from a database @@ -159,4 +158,11 @@ public abstract class AbstractDatabaseHandler { */ public abstract void deleteObject(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, SQLException, NoSuchMethodException, SecurityException; + /** + * Checks if a key exists or not + * @param key + * @return true if this key exists + */ + public abstract boolean objectExits(String key); + } diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/database/managers/IslandsManager.java index 7be405843..93a76b1d4 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/database/managers/IslandsManager.java @@ -1,7 +1,5 @@ package us.tastybento.bskyblock.database.managers; -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; import java.util.HashSet; import java.util.Map.Entry; import java.util.Set; @@ -45,6 +43,7 @@ import us.tastybento.bskyblock.util.Util; */ public class IslandsManager { + private static final boolean DEBUG = false; private BSkyBlock plugin; private BSBDatabase database; @@ -85,6 +84,7 @@ public class IslandsManager { for (Island island : handler.loadObjects()) { islandsByLocation.put(island.getCenter(), island); islandsByUUID.put(island.getOwner(), island); + addToGrid(island); } } catch (Exception e) { // TODO Auto-generated catch block @@ -165,9 +165,60 @@ public class IslandsManager { islandsByLocation.put(location, island); if (owner != null) islandsByUUID.put(owner, island); + addToGrid(island); return island; } + /** + * Adds an island to the grid register + * @param newIsland + */ + private void addToGrid(Island newIsland) { + if (islandGrid.containsKey(newIsland.getMinX())) { + //plugin.getLogger().info("DEBUG: min x is in the grid :" + newIsland.getMinX()); + TreeMap zEntry = islandGrid.get(newIsland.getMinX()); + if (zEntry.containsKey(newIsland.getMinZ())) { + //plugin.getLogger().info("DEBUG: min z is in the grid :" + newIsland.getMinZ()); + // Island already exists + Island conflict = islandGrid.get(newIsland.getMinX()).get(newIsland.getMinZ()); + plugin.getLogger().warning("*** Duplicate or overlapping islands! ***"); + plugin.getLogger().warning( + "Island at (" + newIsland.getCenter().getBlockX() + ", " + newIsland.getCenter().getBlockZ() + ") conflicts with (" + + conflict.getCenter().getBlockX() + ", " + conflict.getCenter().getBlockZ() + ")"); + if (conflict.getOwner() != null) { + plugin.getLogger().warning("Accepted island is owned by " + plugin.getPlayers().getName(conflict.getOwner())); + plugin.getLogger().warning(conflict.getOwner().toString() + ".yml"); + } else { + plugin.getLogger().warning("Accepted island is unowned."); + } + if (newIsland.getOwner() != null) { + plugin.getLogger().warning("Denied island is owned by " + plugin.getPlayers().getName(newIsland.getOwner())); + plugin.getLogger().warning(newIsland.getOwner().toString() + ".yml"); + } else { + plugin.getLogger().warning("Denied island is unowned and was just found in the islands folder. Skipping it..."); + } + plugin.getLogger().warning("Recommend that the denied player file is deleted otherwise weird things can happen."); + return; + } else { + // Add island + //plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ()); + zEntry.put(newIsland.getMinZ(), newIsland); + islandGrid.put(newIsland.getMinX(), zEntry); + // plugin.getLogger().info("Debug: " + newIsland.toString()); + } + } else { + // Add island + //plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ()); + TreeMap zEntry = new TreeMap(); + zEntry.put(newIsland.getMinZ(), newIsland); + islandGrid.put(newIsland.getMinX(), zEntry); + } + } + + /** + * Deletes an island from the database. Does not remove blocks + * @param location + */ public void deleteIsland(Location location){ if (islandsByLocation.containsKey(location)) { Island island = islandsByLocation.get(location); @@ -176,6 +227,29 @@ public class IslandsManager { } islandsByLocation.remove(location); } + // Remove from grid + // plugin.getLogger().info("DEBUG: deleting island at " + location); + Island island = getIslandAt(location); + if (island != null) { + int x = island.getMinX(); + int z = island.getMinZ(); + // plugin.getLogger().info("DEBUG: x = " + x + " z = " + z); + if (islandGrid.containsKey(x)) { + // plugin.getLogger().info("DEBUG: x found"); + TreeMap zEntry = islandGrid.get(x); + if (zEntry.containsKey(z)) { + // plugin.getLogger().info("DEBUG: z found - deleting the island"); + // Island exists - delete it + Island deletedIsland = zEntry.get(z); + deletedIsland.setOwner(null); + deletedIsland.setLocked(false); + zEntry.remove(z); + islandGrid.put(x, zEntry); + } // else { + // plugin.getLogger().info("DEBUG: could not find z"); + // } + } + } } /** @@ -334,14 +408,17 @@ public class IslandsManager { */ public Island getIslandAt(Location location) { if (location == null) { + //plugin.getLogger().info("DEBUG: location is null"); return null; } // World check - if (!inWorld(location)) { + if (!Util.inWorld(location)) { + //plugin.getLogger().info("DEBUG: not in right world"); return null; } // Check if it is spawn if (spawn != null && spawn.onIsland(location)) { + //plugin.getLogger().info("DEBUG: spawn"); return spawn; } return getIslandAt(location.getBlockX(), location.getBlockZ()); @@ -356,6 +433,10 @@ public class IslandsManager { * @return PlayerIsland or null */ public Island getIslandAt(int x, int z) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: getting island at " + x + "," + z); + plugin.getLogger().info("DEBUG: island grid is " + islandGrid.size()); + } Entry> en = islandGrid.floorEntry(x); if (en != null) { Entry ent = en.getValue().floorEntry(z); @@ -363,30 +444,20 @@ public class IslandsManager { // Check if in the island range Island island = ent.getValue(); if (island.inIslandSpace(x, z)) { - // plugin.getLogger().info("DEBUG: In island space"); + if (DEBUG) + plugin.getLogger().info("DEBUG: In island space"); return island; } - //plugin.getLogger().info("DEBUG: not in island space"); + if (DEBUG) + plugin.getLogger().info("DEBUG: not in island space"); } } return null; } - - /** - * Determines if a location is in the island world or not or - * in the new nether if it is activated - * @param loc - * @return true if in the island world - */ - protected boolean inWorld(Location loc) { - // TODO: determine if the world is correct - return true; - } - /** * @param playerUUID - * @return ture if player has island + * @return true if player has island */ public boolean hasIsland(UUID playerUUID) { return islandsByUUID.containsKey(playerUUID); @@ -445,7 +516,8 @@ public class IslandsManager { */ public boolean homeTeleport(final Player player, int number) { Location home = null; - plugin.getLogger().info("home teleport called for #" + number); + if (DEBUG) + plugin.getLogger().info("home teleport called for #" + number); home = getSafeHomeLocation(player.getUniqueId(), number); //plugin.getLogger().info("home get safe loc = " + home); // Check if the player is a passenger in a boat @@ -460,12 +532,14 @@ public class IslandsManager { } } if (home == null) { - plugin.getLogger().info("Fixing home location using safe spot teleport"); + if (DEBUG) + plugin.getLogger().info("Fixing home location using safe spot teleport"); // Try to fix this teleport location and teleport the player if possible new SafeSpotTeleport(plugin, player, plugin.getPlayers().getHomeLocation(player.getUniqueId(), number), number); return true; } - plugin.getLogger().info("DEBUG: home loc = " + home + " teleporting"); + if (DEBUG) + plugin.getLogger().info("DEBUG: home loc = " + home + " teleporting"); //home.getChunk().load(); player.teleport(home); //player.sendBlockChange(home, Material.GLOWSTONE, (byte)0); @@ -747,7 +821,7 @@ public class IslandsManager { public void newIsland(Player player, Schematic schematic) { newIsland(player, schematic, null); } - + /** * Makes an island using schematic. No permission checks are made. They have to be decided * before this method is called. If oldIsland is not null, it will be deleted after the new @@ -767,13 +841,13 @@ public class IslandsManager { plugin.getLogger().info("DEBUG: finding island location"); Location next = getNextIsland(player.getUniqueId()); plugin.getLogger().info("DEBUG: found " + next); - + // Add to the grid Island myIsland = plugin.getIslands().createIsland(next, playerUUID); myIsland.setLevelHandicap(schematic.getLevelHandicap()); // Save the player so that if the server is reset weird things won't happen plugin.getPlayers().save(true); - + // Clear any old home locations (they should be clear, but just in case) plugin.getPlayers().clearHomeLocations(playerUUID); @@ -790,7 +864,7 @@ public class IslandsManager { //plugin.getLogger().info("DEBUG: pasting schematic " + schematic.getName() + " " + schematic.getPerm()); //plugin.getLogger().info("DEBUG: nether world is " + BSkyBlock.getNetherWorld()); // Paste the starting island. If it is a HELL biome, then we start in the Nether - if (Settings.createNether && schematic.isInNether() && Settings.islandNether && IslandWorld.getNetherWorld() != null) { + if (Settings.netherGenerate && schematic.isInNether() && Settings.netherIslands && IslandWorld.getNetherWorld() != null) { // Nether start // Paste the overworld if it exists if (!schematic.getPartnerName().isEmpty()) { @@ -811,7 +885,7 @@ public class IslandsManager { //double diff = (System.nanoTime() - timer)/1000000; //plugin.getLogger().info("DEBUG: nano time = " + diff + " ms"); //plugin.getLogger().info("DEBUG: pasted overworld"); - if (Settings.createNether && Settings.islandNether && IslandWorld.getNetherWorld() != null) { + if (Settings.netherGenerate && Settings.netherIslands && IslandWorld.getNetherWorld() != null) { // Paste the other world schematic final Location netherLoc = next.toVector().toLocation(IslandWorld.getNetherWorld()); if (schematic.getPartnerName().isEmpty()) { @@ -952,7 +1026,7 @@ public class IslandsManager { nextPos.setZ(nextPos.getZ() - Settings.islandDistance); return nextPos; } - + /** * This removes players from an island overworld and nether - used when reseting or deleting an island * Mobs are killed when the chunks are refreshed. @@ -991,4 +1065,232 @@ public class IslandsManager { return handler; } + /** + * @param location + */ + public void removeMobs(Location location) { + // TODO Auto-generated method stub + + } + + /** + * Returns the island being public at the location or null if there is none + * + * @param location + * @return PlayerIsland object + */ + public Island getProtectedIslandAt(Location location) { + //plugin.getLogger().info("DEBUG: getProtectedIslandAt " + location); + // Try spawn + if (spawn != null && spawn.onIsland(location)) { + return spawn; + } + Island island = getIslandAt(location); + if (island == null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: no island at this location"); + return null; + } + if (island.onIsland(location)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: on island"); + return island; + } + if (DEBUG) + plugin.getLogger().info("DEBUG: not in island protection zone"); + return null; + } + + /** + * Indicates whether a player is at the island spawn or not + * + * @param playerLoc + * @return true if they are, false if they are not, or spawn does not exist + */ + public boolean isAtSpawn(Location playerLoc) { + if (spawn == null) { + return false; + } + return spawn.onIsland(playerLoc); + } + + /** + * Checks if a specific location is within the protected range of an island + * owned by the player + * + * @param player + * @param loc + * @return true if location is on island of player + */ + public boolean locationIsOnIsland(final Player player, final Location loc) { + if (player == null) { + return false; + } + // Get the player's island from the grid if it exists + Island island = getIslandAt(loc); + if (island != null) { + //plugin.getLogger().info("DEBUG: island here is " + island.getCenter()); + // On an island in the grid + //plugin.getLogger().info("DEBUG: onIsland = " + island.onIsland(loc)); + //plugin.getLogger().info("DEBUG: members = " + island.getMembers()); + //plugin.getLogger().info("DEBUG: player UUID = " + player.getUniqueId()); + + if (island.onIsland(loc) && island.getMembers().contains(player.getUniqueId())) { + //plugin.getLogger().info("DEBUG: allowed"); + // In a protected zone but is on the list of acceptable players + return true; + } else { + // Not allowed + //plugin.getLogger().info("DEBUG: not allowed"); + return false; + } + } else { + //plugin.getLogger().info("DEBUG: no island at this location"); + } + // Not in the grid, so do it the old way + // Make a list of test locations and test them + Set islandTestLocations = new HashSet(); + if (plugin.getPlayers().hasIsland(player.getUniqueId()) || plugin.getPlayers().inTeam(player.getUniqueId())) { + islandTestLocations.add(getIslandLocation(player.getUniqueId())); + } + // TODO: Check any coop locations + /* + islandTestLocations.addAll(CoopPlay.getInstance().getCoopIslands(player)); + if (islandTestLocations.isEmpty()) { + return false; + }*/ + // Run through all the locations + for (Location islandTestLocation : islandTestLocations) { + if (loc.getWorld().equals(islandTestLocation.getWorld())) { + if (loc.getX() >= islandTestLocation.getX() - Settings.islandProtectionRange / 2 + && loc.getX() < islandTestLocation.getX() + Settings.islandProtectionRange / 2 + && loc.getZ() >= islandTestLocation.getZ() - Settings.islandProtectionRange / 2 + && loc.getZ() < islandTestLocation.getZ() + Settings.islandProtectionRange / 2) { + return true; + } + } + } + return false; + } + + /** + * Checks if an online player is in the protected area of their island, a team island or a + * coop island + * + * @param player + * @return true if on valid island, false if not + */ + public boolean playerIsOnIsland(final Player player) { + return playerIsOnIsland(player, true); + } + + /** + * Checks if an online player is in the protected area of their island, a team island or a + * coop island + * @param player + * @param coop - if true, coop islands are included + * @return true if on valid island, false if not + */ + public boolean playerIsOnIsland(final Player player, boolean coop) { + return locationIsAtHome(player, coop, player.getLocation()); + } + + /** + * Checks if a location is within the home boundaries of a player. If coop is true, this check includes coop players. + * @param player + * @param coop + * @param loc + * @return true if the location is within home boundaries + */ + public boolean locationIsAtHome(final Player player, boolean coop, Location loc) { + // Make a list of test locations and test them + Set islandTestLocations = new HashSet(); + if (plugin.getPlayers().hasIsland(player.getUniqueId()) || plugin.getPlayers().inTeam(player.getUniqueId())) { + islandTestLocations.add(plugin.getIslands().getIslandLocation(player.getUniqueId())); + // If new Nether + if (Settings.netherGenerate && Settings.netherIslands && IslandWorld.getNetherWorld() != null) { + islandTestLocations.add(netherIsland(plugin.getIslands().getIslandLocation(player.getUniqueId()))); + } + } + // TODO: Check coop locations + /* + if (coop) { + islandTestLocations.addAll(CoopPlay.getInstance().getCoopIslands(player)); + }*/ + if (islandTestLocations.isEmpty()) { + return false; + } + // Run through all the locations + for (Location islandTestLocation : islandTestLocations) { + // Must be in the same world as the locations being checked + // Note that getWorld can return null if a world has been deleted on the server + if (islandTestLocation != null && islandTestLocation.getWorld() != null && islandTestLocation.getWorld().equals(loc.getWorld())) { + int protectionRange = Settings.islandProtectionRange; + if (getIslandAt(islandTestLocation) != null) { + // Get the protection range for this location if possible + Island island = getProtectedIslandAt(islandTestLocation); + if (island != null) { + // We are in a protected island area. + protectionRange = island.getProtectionRange(); + } + } + if (loc.getX() > islandTestLocation.getX() - protectionRange / 2 + && loc.getX() < islandTestLocation.getX() + protectionRange / 2 + && loc.getZ() > islandTestLocation.getZ() - protectionRange / 2 + && loc.getZ() < islandTestLocation.getZ() + protectionRange / 2) { + return true; + } + } + } + return false; + } + + /** + * Generates a Nether version of the locations + * @param islandLocation + * @return + */ + private Location netherIsland(Location islandLocation) { + //plugin.getLogger().info("DEBUG: netherworld = " + ASkyBlock.getNetherWorld()); + return islandLocation.toVector().toLocation(IslandWorld.getNetherWorld()); + } + + /** + * Get name of the island owned by owner + * @param owner + * @return Returns the name of owner's island, or the owner's name if there is none. + */ + public String getIslandName(UUID owner) { + String result = plugin.getPlayers().getName(owner); + if (islandsByUUID.containsKey(owner)) { + Island island = islandsByUUID.get(owner); + if (!island.getName().isEmpty()) { + result = island.getName(); + } + } + return ChatColor.translateAlternateColorCodes('&', result) + ChatColor.RESET; + } + + /** + * Set the island name + * @param owner + * @param name + */ + public void setIslandName(UUID owner, String name) { + if (islandsByUUID.containsKey(owner)) { + Island island = islandsByUUID.get(owner); + island.setName(name); + } + } + + /** + * @return the spawnPoint or null if spawn does not exist + */ + public Location getSpawnPoint() { + //plugin.getLogger().info("DEBUG: getting spawn point : " + spawn.getSpawnPoint()); + if (spawn == null) + return null; + return spawn.getSpawnPoint(); + } + } diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java b/src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java index b97d83a29..1bedad6ff 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java +++ b/src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java @@ -1,5 +1,8 @@ package us.tastybento.bskyblock.database.managers; +import java.beans.IntrospectionException; +import java.lang.reflect.InvocationTargetException; +import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; import java.util.Set; @@ -17,6 +20,7 @@ import us.tastybento.bskyblock.util.VaultHelper; public class PlayersManager{ + private static final boolean DEBUG = false; private BSkyBlock plugin; private BSBDatabase database; private AbstractDatabaseHandler handler; @@ -42,7 +46,7 @@ public class PlayersManager{ } /** - * Load all players + * Load all players - not normally used as to load all players into memory will be wasteful */ public void load(){ playerCache.clear(); @@ -105,13 +109,30 @@ public class PlayersManager{ * Cache control methods */ + /** + * Adds a player to the cache + * @param playerUUID + * @return the players object + */ public Players addPlayer(final UUID playerUUID) { if (playerUUID == null) return null; - //plugin.getLogger().info("DEBUG: added player " + playerUUID); + //plugin.getLogger().info("DEBUG: adding player " + playerUUID); if (!playerCache.containsKey(playerUUID)) { - plugin.getLogger().info("DEBUG: new player"); - final Players player = new Players(playerUUID); + //plugin.getLogger().info("DEBUG: player not in cache"); + Players player = null; + // If the player is in the database, load it, otherwise create a new player + if (handler.objectExits(playerUUID.toString())) { + //plugin.getLogger().info("DEBUG: player in database"); + try { + player = handler.loadObject(playerUUID.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + //plugin.getLogger().info("DEBUG: new player"); + player = new Players(playerUUID); + } playerCache.put(playerUUID, player); return player; } else { @@ -127,10 +148,18 @@ public class PlayersManager{ * */ public void removeOnlinePlayer(final UUID player) { + // plugin.getLogger().info("Removing player from cache: " + player); if (playerCache.containsKey(player)) { - //database.savePlayerData(playerCache.get(player)); - playerCache.remove(player); - // plugin.getLogger().info("Removing player from cache: " + player); + try { + handler.saveObject(playerCache.get(player)); + playerCache.remove(player); + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException | SecurityException + | InstantiationException | NoSuchMethodException + | IntrospectionException | SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } @@ -139,7 +168,7 @@ public class PlayersManager{ */ public void removeAllPlayers() { for (UUID pl : playerCache.keySet()) { - //database.savePlayerData(playerCache.get(pl)); + removeOnlinePlayer(pl); } playerCache.clear(); } @@ -163,9 +192,7 @@ public class PlayersManager{ return true; } else { // Get from the database - do not add to cache yet - //return database.isPlayerKnown(uniqueID) ? true: false; - // TODO - return false; + return handler.objectExits(uniqueID.toString()); } } @@ -301,7 +328,6 @@ public class PlayersManager{ * @param adminCheck - if made via an admin call, this will go out to the 'net and grab - may cause lag * @return UUID of player or null if unknown */ - @SuppressWarnings("deprecation") public UUID getUUID(String string, boolean adminCheck) { // Look in the database if it ready //return database.getUUID(string, adminCheck); @@ -556,7 +582,7 @@ public class PlayersManager{ public void removeInTeleport(UUID uniqueId) { inTeleport.remove(uniqueId); } - + /** * @param uniqueId * @return true if a player is mid-teleport @@ -571,8 +597,30 @@ public class PlayersManager{ */ public void resetPlayer(Player player) { // TODO Auto-generated method stub - - } - + } + + /** + * Saves the player to the database + * @param playerUUID + */ + public void save(UUID playerUUID) { + if (playerCache.containsKey(playerUUID)) { + Players player = playerCache.get(playerUUID); + try { + handler.saveObject(player); + if (DEBUG) + plugin.getLogger().info("DEBUG: " + playerUUID + " saved"); + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException | SecurityException + | InstantiationException | NoSuchMethodException + | IntrospectionException | SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else { + if (DEBUG) + plugin.getLogger().info("DEBUG: " + playerUUID + " is not in the cache to save"); + } + } } diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseConnecter.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseConnecter.java index d473bf1b5..554208573 100644 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseConnecter.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseConnecter.java @@ -60,4 +60,10 @@ public class MySQLDatabaseConnecter implements DatabaseConnecter { } + @Override + public boolean uniqueIdExists(String simpleName, String key) { + // Not used + return false; + } + } diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java index 9bf1ecde6..ba1028f2f 100644 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java @@ -260,8 +260,6 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { sb.append("SELECT "); sb.append(super.getColumns(false)); sb.append(" FROM "); - - /* We assume the table-name exactly matches the canonical Name of T */ sb.append("`"); sb.append(type.getCanonicalName()); sb.append("`"); @@ -269,6 +267,7 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { return sb.toString(); } + /* (non-Javadoc) * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#createInsertQuery() */ @@ -292,6 +291,7 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { return sb.toString(); } + @Override protected String createDeleteQuery() { return "DELETE FROM [table_name] WHERE uniqueId = ?"; } @@ -781,6 +781,30 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { } - + /* (non-Javadoc) + * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#objectExits(java.lang.String) + */ + @Override + public boolean objectExits(String key) { + Connection connection = null; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + String query = "SELECT * FROM `" + type.getCanonicalName() + "` WHERE uniqueId = ?"; + try { + connection = databaseConnecter.createConnection(); + preparedStatement = connection.prepareStatement(query); + preparedStatement.setString(1, key); + resultSet = preparedStatement.executeQuery(); + return resultSet.next(); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + MySQLDatabaseResourceCloser.close(resultSet); + MySQLDatabaseResourceCloser.close(preparedStatement); + MySQLDatabaseResourceCloser.close(connection); + } + return false; + } } diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java index df5286fa1..b1b0d0715 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java @@ -7,11 +7,16 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.World; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; import us.tastybento.bskyblock.api.events.island.IslandLockEvent; import us.tastybento.bskyblock.api.events.island.IslandUnlockEvent; import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.util.Util; /** * Stores all the info about an island @@ -354,6 +359,8 @@ public class Island extends DataObject { private int levelHandicap; + private Location spawnPoint; + public Island() {}; public Island(Location location, UUID owner, int protectionRange) { @@ -424,6 +431,7 @@ public class Island extends DataObject { public long getCreatedDate(){ return createdDate; } + /** * Get the Island Guard flag status * @param flag @@ -433,6 +441,11 @@ public class Island extends DataObject { if(flags.containsKey(flag)) { return flags.get(flag); } else { + if (flag.equals(SettingsFlag.ANIMAL_SPAWN) || flag.equals(SettingsFlag.MONSTER_SPAWN)) { + flags.put(flag, true); + return true; + } + flags.put(flag, false); return false; } } @@ -484,8 +497,16 @@ public class Island extends DataObject { /** * @return the island display name or the owner's name if none is set */ - public String getName(){ - return (name != null && owner != null) ? name : Bukkit.getServer().getOfflinePlayer(owner).getName(); + public String getName() { + if (name != null) { + return name; + } + if (owner != null) { + OfflinePlayer player = Bukkit.getServer().getOfflinePlayer(owner); + name = player.getName(); + return player.getName(); + } + return ""; } /** @@ -603,8 +624,8 @@ public class Island extends DataObject { */ public boolean onIsland(Location target) { if (center.getWorld() != null) { - if (target.getBlockX() >= minProtectedX && target.getBlockX() < (minProtectedX + protectionRange) - && target.getBlockZ() >= minProtectedZ && target.getBlockZ() < (minProtectedZ + protectionRange)) { + if (target.getBlockX() >= minProtectedX && target.getBlockX() < (minProtectedX + protectionRange*2) + && target.getBlockZ() >= minProtectedZ && target.getBlockZ() < (minProtectedZ + protectionRange*2)) { return true; } } @@ -836,4 +857,78 @@ public class Island extends DataObject { this.levelHandicap = levelHandicap; } + /** + * @return true if island is locked, false if not + */ + public boolean isLocked() { + return locked; + } + + /** + * @return spawn + */ + public boolean isSpawn() { + return spawn; + } + + /** + * @param material + * @return count of how many tile entities of type mat are on the island at last count. Counts are done when a player places + * a tile entity. + */ + public int getTileEntityCount(Material material, World world) { + int result = 0; + for (int x = getMinProtectedX() /16; x <= (getMinProtectedX() + getProtectionRange() - 1)/16; x++) { + for (int z = getMinProtectedZ() /16; z <= (getMinProtectedZ() + getProtectionRange() - 1)/16; z++) { + for (BlockState holder : world.getChunkAt(x, z).getTileEntities()) { + //plugin.getLogger().info("DEBUG: tile entity: " + holder.getType()); + if (onIsland(holder.getLocation())) { + if (holder.getType() == material) { + result++; + } else if (material.equals(Material.REDSTONE_COMPARATOR_OFF)) { + if (holder.getType().equals(Material.REDSTONE_COMPARATOR_ON)) { + result++; + } + } else if (material.equals(Material.FURNACE)) { + if (holder.getType().equals(Material.BURNING_FURNACE)) { + result++; + } + } else if (material.toString().endsWith("BANNER")) { + if (holder.getType().toString().endsWith("BANNER")) { + result++; + } + } else if (material.equals(Material.WALL_SIGN) || material.equals(Material.SIGN_POST)) { + if (holder.getType().equals(Material.WALL_SIGN) || holder.getType().equals(Material.SIGN_POST)) { + result++; + } + } + } + } + for (Entity holder : world.getChunkAt(x, z).getEntities()) { + //plugin.getLogger().info("DEBUG: entity: " + holder.getType()); + if (holder.getType().toString().equals(material.toString()) && onIsland(holder.getLocation())) { + result++; + } + } + } + } + return result; + } + + public boolean inIslandSpace(Location location) { + if (Util.inWorld(location)) { + return inIslandSpace(location.getBlockX(), location.getBlockZ()); + } + return false; + } + + public void setSpawnPoint(Location location) { + spawnPoint = location; + + } + + public Location getSpawnPoint() { + return spawnPoint; + } + } \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Players.java b/src/main/java/us/tastybento/bskyblock/database/objects/Players.java index a526e2601..6d601a2e2 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Players.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Players.java @@ -44,6 +44,7 @@ public class Players extends DataObject { this.locale = ""; this.useControlPanel = Settings.useControlPanel; this.kickedList = new HashMap(); + this.playerName = Bukkit.getServer().getOfflinePlayer(uniqueId).getName(); } /** diff --git a/src/main/java/us/tastybento/bskyblock/generators/ChunkGeneratorWorld.java b/src/main/java/us/tastybento/bskyblock/generators/ChunkGeneratorWorld.java index c514b6c0e..c97c96407 100644 --- a/src/main/java/us/tastybento/bskyblock/generators/ChunkGeneratorWorld.java +++ b/src/main/java/us/tastybento/bskyblock/generators/ChunkGeneratorWorld.java @@ -1,21 +1,4 @@ -/******************************************************************************* - * This file is part of BSkyBlock. - * - * BSkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BSkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ASkyBlock. If not, see . - *******************************************************************************/ - -package us.tastybento.bskyblock.generators; + package us.tastybento.bskyblock.generators; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/us/tastybento/bskyblock/generators/IslandWorld.java b/src/main/java/us/tastybento/bskyblock/generators/IslandWorld.java index af5b3167e..47744781f 100644 --- a/src/main/java/us/tastybento/bskyblock/generators/IslandWorld.java +++ b/src/main/java/us/tastybento/bskyblock/generators/IslandWorld.java @@ -33,11 +33,11 @@ public class IslandWorld { islandWorld = WorldCreator.name(Settings.worldName).type(WorldType.FLAT).environment(World.Environment.NORMAL).generator(new ChunkGeneratorWorld()) .createWorld(); // Make the nether if it does not exist - if (Settings.createNether) { + if (Settings.netherGenerate) { if (plugin.getServer().getWorld(Settings.worldName + "_nether") == null) { Bukkit.getLogger().info("Creating " + plugin.getName() + "'s Nether..."); } - if (!Settings.islandNether) { + if (!Settings.netherIslands) { netherWorld = WorldCreator.name(Settings.worldName + "_nether").type(WorldType.NORMAL).environment(World.Environment.NETHER).createWorld(); } else { netherWorld = WorldCreator.name(Settings.worldName + "_nether").type(WorldType.FLAT).generator(new ChunkGeneratorWorld()) @@ -45,11 +45,11 @@ public class IslandWorld { } } // Make the end if it does not exist - if (Settings.createEnd) { + if (Settings.endGenerate) { if (plugin.getServer().getWorld(Settings.worldName + "_the_end") == null) { Bukkit.getLogger().info("Creating " + plugin.getName() + "'s End World..."); } - if (!Settings.islandEnd) { + if (!Settings.endIslands) { endWorld = WorldCreator.name(Settings.worldName + "_the_end").type(WorldType.NORMAL).environment(World.Environment.THE_END).createWorld(); } else { endWorld = WorldCreator.name(Settings.worldName + "_the_end").type(WorldType.FLAT).generator(new ChunkGeneratorWorld()) @@ -70,13 +70,13 @@ public class IslandWorld { "mv modify set generator " + plugin.getName() + " " + Settings.worldName)) { Bukkit.getLogger().severe("Multiverse is out of date! - Upgrade to latest version!"); } - if (netherWorld != null && Settings.createNether && Settings.islandNether) { + if (netherWorld != null && Settings.netherGenerate && Settings.netherIslands) { Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv import " + Settings.worldName + "_nether nether -g " + plugin.getName()); Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv modify set generator " + plugin.getName() + " " + Settings.worldName + "_nether"); } - if (endWorld != null && Settings.createEnd && Settings.islandEnd) { + if (endWorld != null && Settings.endGenerate && Settings.endIslands) { Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv import " + Settings.worldName + "_the_end end -g " + plugin.getName()); Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), diff --git a/src/main/java/us/tastybento/bskyblock/generators/NetherPopulator.java b/src/main/java/us/tastybento/bskyblock/generators/NetherPopulator.java index 77fc2a2a1..b7d9367ea 100644 --- a/src/main/java/us/tastybento/bskyblock/generators/NetherPopulator.java +++ b/src/main/java/us/tastybento/bskyblock/generators/NetherPopulator.java @@ -1,20 +1,3 @@ -/******************************************************************************* - * This file is part of BSkyBlock. - * - * BSkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BSkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with BSkyBlock. If not, see . - *******************************************************************************/ - package us.tastybento.bskyblock.generators; import java.util.Random; diff --git a/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java b/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java new file mode 100644 index 000000000..188acab45 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java @@ -0,0 +1,95 @@ +package us.tastybento.bskyblock.listeners; + +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.database.managers.PlayersManager; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +public class JoinLeaveListener implements Listener { + + private static final boolean DEBUG = false; + private BSkyBlock plugin; + private PlayersManager players; + + /** + * @param plugin + */ + public JoinLeaveListener(BSkyBlock plugin) { + this.plugin = plugin; + this.players = plugin.getPlayers(); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerJoin(final PlayerJoinEvent event) { + Player player = event.getPlayer(); + if (player == null) { + return; + } + UUID playerUUID = player.getUniqueId(); + if (playerUUID == null) { + return; + } + if (plugin.getPlayers().isAKnownPlayer(playerUUID)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: known player"); + // Load player + players.addPlayer(playerUUID); + // Reset resets if the admin changes it to or from unlimited + if (Settings.resetLimit < players.getResetsLeft(playerUUID) || (Settings.resetLimit >= 0 && players.getResetsLeft(playerUUID) < 0)) { + players.setResetsLeft(playerUUID, Settings.resetLimit); + } + if (DEBUG) + plugin.getLogger().info("DEBUG: Setting player's name"); + // Set the player's name (it may have changed), but only if it isn't empty + if (!player.getName().isEmpty()) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Player name is " + player.getName()); + players.setPlayerName(playerUUID, player.getName()); + if (DEBUG) + plugin.getLogger().info("DEBUG: Saving player"); + players.save(playerUUID); + } else { + plugin.getLogger().warning("Player that just logged in has no name! " + playerUUID.toString()); + } + if (Settings.logInRemoveMobs) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Removing mobs"); + plugin.getIslands().removeMobs(player.getLocation()); + } + + // Check if they logged in to a locked island and expel them or if they are banned + Island currentIsland = plugin.getIslands().getIslandAt(player.getLocation()); + if (currentIsland != null && (currentIsland.isLocked() || plugin.getPlayers().isBanned(currentIsland.getOwner(),player.getUniqueId()))) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Current island is locked, or player is banned"); + if (!currentIsland.getMembers().contains(playerUUID) && !player.isOp() + && !VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) { + if (DEBUG) + plugin.getLogger().info("DEBUG: No bypass - teleporting"); + Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player.getUniqueId()).get("locked.islandlocked")); + plugin.getIslands().homeTeleport(player); + } + } + } else { + if (DEBUG) + plugin.getLogger().info("DEBUG: not a known player"); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerQuit(final PlayerQuitEvent event) { + players.removeOnlinePlayer(event.getPlayer().getUniqueId()); + } +} diff --git a/src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java b/src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java new file mode 100644 index 000000000..cf993fda2 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/NetherPortals.java @@ -0,0 +1,256 @@ +package us.tastybento.bskyblock.listeners; + +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPortalEvent; +import org.bukkit.event.player.PlayerPortalEvent; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.database.managers.IslandsManager; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; +import us.tastybento.bskyblock.generators.IslandWorld; +import us.tastybento.bskyblock.schematics.Schematic; +import us.tastybento.bskyblock.schematics.Schematic.PasteReason; +import us.tastybento.bskyblock.util.SafeSpotTeleport; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +public class NetherPortals implements Listener { + private final BSkyBlock plugin; + private final static boolean DEBUG = false; + + public NetherPortals(BSkyBlock plugin) { + this.plugin = plugin; + } + + /** + * This handles non-player portal use + * Currently disables portal use by entities + * + * @param event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityPortal(EntityPortalEvent event) { + if (DEBUG) + plugin.getLogger().info("DEBUG: nether portal entity " + event.getFrom().getBlock().getType()); + // If the nether is disabled then quit immediately + if (!Settings.netherGenerate || IslandWorld.getNetherWorld() == null) { + return; + } + if (event.getEntity() == null) { + return; + } + if (event.getFrom() != null && event.getFrom().getBlock().getType().equals(Material.ENDER_PORTAL)) { + event.setCancelled(true); + // Same action for all worlds except the end itself + if (!event.getFrom().getWorld().getEnvironment().equals(Environment.THE_END)) { + if (plugin.getServer().getWorld(Settings.worldName + "_the_end") != null) { + // The end exists + Location end_place = plugin.getServer().getWorld(Settings.worldName + "_the_end").getSpawnLocation(); + event.getEntity().teleport(end_place); + if (DEBUG) + plugin.getLogger().info("DEBUG: Result teleported " + event.getEntityType() + " to " + end_place); + return; + } + } + return; + } + Location currentLocation = event.getFrom().clone(); + String currentWorld = currentLocation.getWorld().getName(); + // Only operate if this is Island territory + if (!currentWorld.equalsIgnoreCase(Settings.worldName) && !currentWorld.equalsIgnoreCase(Settings.worldName + "_nether")) { + return; + } + // No entities may pass with the old nether + if (!Settings.netherIslands) { + event.setCancelled(true); + return; + } + // New nether + // Entities can pass only if there are adjoining portals + Location dest = event.getFrom().toVector().toLocation(IslandWorld.getIslandWorld()); + if (event.getFrom().getWorld().getEnvironment().equals(Environment.NORMAL)) { + dest = event.getFrom().toVector().toLocation(IslandWorld.getNetherWorld()); + } + // Vehicles + if (event.getEntity() instanceof Vehicle) { + Vehicle vehicle = (Vehicle)event.getEntity(); + vehicle.eject(); + } + new SafeSpotTeleport(plugin, event.getEntity(), dest); + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerPortal(PlayerPortalEvent event) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Player portal event - reason =" + event.getCause()); + UUID playerUUID = event.getPlayer().getUniqueId(); + // If the nether is disabled then quit immediately + if (!Settings.netherGenerate || IslandWorld.getNetherWorld() == null) { + return; + } + Location currentLocation = event.getFrom().clone(); + String currentWorld = currentLocation.getWorld().getName(); + if (!currentWorld.equalsIgnoreCase(Settings.worldName) && !currentWorld.equalsIgnoreCase(Settings.worldName + "_nether") + && !currentWorld.equalsIgnoreCase(Settings.worldName + "_the_end")) { + if (DEBUG) + plugin.getLogger().info("DEBUG: not right world"); + return; + } + // Check if player has permission + Island island = plugin.getIslands().getIslandAt(currentLocation); + // TODO: if ((island == null && !Settings.defaultWorldSettings.get(SettingsFlag.PORTAL)) + if (island == null + || (island != null && !(island.getFlag(SettingsFlag.PORTAL) || island.getMembers().contains(event.getPlayer().getUniqueId())))) { + // Portals use is not allowed + if (DEBUG) + plugin.getLogger().info("DEBUG: Portal use not allowed"); + if (!event.getPlayer().isOp() && !VaultHelper.hasPerm(event.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + Util.sendMessage(event.getPlayer(), ChatColor.RED + plugin.getLocale(event.getPlayer().getUniqueId()).get("island.protected")); + event.setCancelled(true); + return; + } + } + // Determine what portal it is + switch (event.getCause()) { + case END_PORTAL: + if (DEBUG) + plugin.getLogger().info("DEBUG: End portal"); + // Same action for all worlds except the end itself + if (!event.getFrom().getWorld().getEnvironment().equals(Environment.THE_END)) { + if (plugin.getServer().getWorld(Settings.worldName + "_the_end") != null) { + // The end exists + event.setCancelled(true); + Location end_place = plugin.getServer().getWorld(Settings.worldName + "_the_end").getSpawnLocation(); + if (IslandsManager.isSafeLocation(end_place)) { + event.getPlayer().teleport(end_place); + // event.getPlayer().sendBlockChange(end_place, + // end_place.getBlock().getType(),end_place.getBlock().getData()); + return; + } else { + Util.sendMessage(event.getPlayer(), ChatColor.RED + plugin.getLocale(event.getPlayer().getUniqueId()).get("warps.error.NotSafe")); + plugin.getIslands().homeTeleport(event.getPlayer()); + return; + } + } + } else { + event.setCancelled(true); + plugin.getIslands().homeTeleport(event.getPlayer()); + } + break; + case NETHER_PORTAL: + if (DEBUG) + plugin.getLogger().info("DEBUG: nether portal"); + // Get the home world of this player + World homeWorld = IslandWorld.getIslandWorld(); + Location home = plugin.getPlayers().getHomeLocation(event.getPlayer().getUniqueId()); + if (home != null) { + homeWorld = home.getWorld(); + } + if (!Settings.netherIslands) { + // Legacy action + if (event.getFrom().getWorld().getEnvironment().equals(Environment.NORMAL)) { + // Going to Nether + if (homeWorld.getEnvironment().equals(Environment.NORMAL)) { + // Home world is over world + event.setTo(IslandWorld.getNetherWorld().getSpawnLocation()); + event.useTravelAgent(true); + } else { + // Home world is nether - going home + event.useTravelAgent(false); + Location dest = plugin.getIslands().getSafeHomeLocation(playerUUID,1); + if (dest != null) { + event.setTo(dest); + } else { + event.setCancelled(true); + new SafeSpotTeleport(plugin, event.getPlayer(), plugin.getIslands().getIslandLocation(playerUUID), 1); + } + } + } else { + // Going to Over world + if (homeWorld.getEnvironment().equals(Environment.NORMAL)) { + // Home world is over world + event.useTravelAgent(false); + Location dest = plugin.getIslands().getSafeHomeLocation(playerUUID,1); + if (dest != null) { + event.setTo(dest); + } else { + event.setCancelled(true); + new SafeSpotTeleport(plugin, event.getPlayer(), plugin.getIslands().getIslandLocation(playerUUID), 1); + } + } else { + // Home world is nether + event.setTo(IslandWorld.getIslandWorld().getSpawnLocation()); + event.useTravelAgent(true); + } + } + } else { + // Island Nether + if (DEBUG) + plugin.getLogger().info("DEBUG: Island nether"); + // Get location of the island where the player is at + if (island == null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: island is null"); + event.setCancelled(true); + return; + } + // Can go both ways now + Location overworldIsland = island.getCenter().toVector().toLocation(IslandWorld.getIslandWorld()); + Location netherIsland = island.getCenter().toVector().toLocation(IslandWorld.getNetherWorld()); + //Location dest = event.getFrom().toVector().toLocation(IslandWorld.getIslandWorld()); + if (event.getFrom().getWorld().getEnvironment().equals(Environment.NORMAL)) { + // Going to Nether + // Check that there is a nether island there. Due to legacy reasons it may not exist + if (DEBUG) + plugin.getLogger().info("DEBUG: island center = " + island.getCenter()); + if (netherIsland.getBlock().getType() != Material.BEDROCK) { + // Check to see if there is anything there + if (plugin.getIslands().bigScan(netherIsland, 20) == null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: big scan is null"); + plugin.getLogger().warning("Creating nether island for " + event.getPlayer().getName() + " using default nether schematic"); + Schematic nether = plugin.getSchematics().getSchematic("nether"); + if (nether != null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: pasting at " + island.getCenter().toVector()); + nether.pasteSchematic(netherIsland, event.getPlayer(), false, PasteReason.PARTNER, island); + } else { + plugin.getLogger().severe("Cannot teleport player to nether because there is no nether schematic"); + event.setCancelled(true); + Util.sendMessage(event.getPlayer(), ChatColor.RED + plugin.getLocale(event.getPlayer().getUniqueId()).get("warps.error.NotSafe")); + return; + } + } + } + if (DEBUG) + plugin.getLogger().info("DEBUG: Teleporting to " + event.getFrom().toVector().toLocation(IslandWorld.getNetherWorld())); + event.setCancelled(true); + // Teleport using the new safeSpot teleport + new SafeSpotTeleport(plugin, event.getPlayer(), netherIsland); + return; + } + // Going to the over world - if there isn't an island, do nothing + event.setCancelled(true); + // Teleport using the new safeSpot teleport + new SafeSpotTeleport(plugin, event.getPlayer(), overworldIsland); + } + break; + default: + break; + } + } + +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java new file mode 100644 index 000000000..470a0c90f --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/FlyingMobEvents.java @@ -0,0 +1,219 @@ +package us.tastybento.bskyblock.listeners.protection; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.WeakHashMap; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Wither; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ExplosionPrimeEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.util.Util; + +/** + * This class manages flying mobs. If they exist the spawned island's limits they will be removed. + * + * @author tastybento + * + */ +public class FlyingMobEvents implements Listener { + private final BSkyBlock plugin; + private final static boolean DEBUG = false; + private WeakHashMap mobSpawnInfo; + + /** + * @param plugin + */ + public FlyingMobEvents(BSkyBlock plugin) { + this.plugin = plugin; + this.mobSpawnInfo = new WeakHashMap(); + new BukkitRunnable() { + + public void run() { + //Bukkit.getLogger().info("DEBUG: checking - mobspawn size = " + mobSpawnInfo.size()); + Iterator> it = mobSpawnInfo.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + if (entry.getKey() == null) { + //Bukkit.getLogger().info("DEBUG: removing null entity"); + it.remove(); + } else { + if (entry.getKey() instanceof LivingEntity) { + if (!entry.getValue().inIslandSpace(entry.getKey().getLocation())) { + //Bukkit.getLogger().info("DEBUG: removing entity outside of island"); + it.remove(); + // Kill mob + LivingEntity mob = (LivingEntity)entry.getKey(); + mob.setHealth(0); + entry.getKey().remove(); + } else { + //Bukkit.getLogger().info("DEBUG: entity " + entry.getKey().getName() + " is in island space"); + } + } else { + // Not living entity + it.remove(); + } + } + } + } + + }.runTaskTimer(plugin, 20L, 20L); + } + + /** + * Track where the mob was created. This will determine its allowable movement zone. + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void mobSpawn(CreatureSpawnEvent e) { + // Only cover withers in the island world + if (!Util.inWorld(e.getEntity())) { + return; + } + if (!e.getEntityType().equals(EntityType.WITHER) && !e.getEntityType().equals(EntityType.BLAZE) && !e.getEntityType().equals(EntityType.GHAST)) { + return; + } + if (DEBUG) { + plugin.getLogger().info("Flying mobs " + e.getEventName()); + } + // Store where this mob originated + Island island = plugin.getIslands().getIslandAt(e.getLocation()); + if (island != null) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: Mob spawned on known island - id = " + e.getEntity().getUniqueId()); + } + mobSpawnInfo.put(e.getEntity(),island); + } // Else do nothing - maybe an Op spawned it? If so, on their head be it! + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void MobExplosion(EntityExplodeEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + // Only cover in the island world + if (e.getEntity() == null || !Util.inWorld(e.getEntity())) { + return; + } + if (mobSpawnInfo.containsKey(e.getEntity().getUniqueId())) { + // We know about this mob + if (DEBUG) { + plugin.getLogger().info("DEBUG: We know about this mob"); + } + if (!mobSpawnInfo.get(e.getEntity().getUniqueId()).inIslandSpace(e.getLocation())) { + // Cancel the explosion and block damage + if (DEBUG) { + plugin.getLogger().info("DEBUG: cancel flying mob explosion"); + } + e.blockList().clear(); + e.setCancelled(true); + } + } + } + + /** + * Deal with pre-explosions + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void WitherExplode(ExplosionPrimeEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + // Only cover withers in the island world + if (!Util.inWorld(e.getEntity()) || e.getEntity() == null) { + return; + } + // The wither or wither skulls can both blow up + if (e.getEntityType() == EntityType.WITHER) { + //plugin.getLogger().info("DEBUG: Wither"); + // Check the location + if (mobSpawnInfo.containsKey(e.getEntity().getUniqueId())) { + // We know about this wither + if (DEBUG) { + plugin.getLogger().info("DEBUG: We know about this wither"); + } + if (!mobSpawnInfo.get(e.getEntity()).inIslandSpace(e.getEntity().getLocation())) { + // Cancel the explosion + if (DEBUG) { + plugin.getLogger().info("DEBUG: cancelling wither pre-explosion"); + } + e.setCancelled(true); + } + } + // Testing only e.setCancelled(true); + } + if (e.getEntityType() == EntityType.WITHER_SKULL) { + //plugin.getLogger().info("DEBUG: Wither skull"); + // Get shooter + Projectile projectile = (Projectile)e.getEntity(); + if (projectile.getShooter() instanceof Wither) { + //plugin.getLogger().info("DEBUG: shooter is wither"); + Wither wither = (Wither)projectile.getShooter(); + // Check the location + if (mobSpawnInfo.containsKey(wither.getUniqueId())) { + // We know about this wither + if (DEBUG) { + plugin.getLogger().info("DEBUG: We know about this wither"); + } + if (!mobSpawnInfo.get(wither.getUniqueId()).inIslandSpace(e.getEntity().getLocation())) { + // Cancel the explosion + if (DEBUG) { + plugin.getLogger().info("DEBUG: cancel wither skull explosion"); + } + e.setCancelled(true); + } + } + } + } + } + + /** + * Withers change blocks to air after they are hit (don't know why) + * This prevents this when the wither has been spawned by a visitor + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void WitherChangeBlocks(EntityChangeBlockEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + // Only cover withers in the island world + if (e.getEntityType() != EntityType.WITHER || !Util.inWorld(e.getEntity()) ) { + return; + } + if (mobSpawnInfo.containsKey(e.getEntity())) { + // We know about this wither + if (DEBUG) { + plugin.getLogger().info("DEBUG: We know about this wither"); + } + if (!mobSpawnInfo.get(e.getEntity()).inIslandSpace(e.getEntity().getLocation())) { + // Cancel the block changes + if (DEBUG) { + plugin.getLogger().info("DEBUG: cancelled wither block change"); + } + e.setCancelled(true); + } + } + } + + /** + * Clean up the hashmap. It's probably not needed, but just in case. + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void MobDeath(EntityDeathEvent e) { + mobSpawnInfo.remove(e.getEntity()); + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/InventorySave.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/InventorySave.java new file mode 100644 index 000000000..84664b11a --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/InventorySave.java @@ -0,0 +1,66 @@ +package us.tastybento.bskyblock.listeners.protection; + +import java.util.HashMap; +import java.util.UUID; + +import org.bukkit.entity.Player; + +import us.tastybento.bskyblock.BSkyBlock; + +/** + * Stashes inventories when required for a player + * + * @author tastybento + * + */ +public class InventorySave { + private static InventorySave instance = new InventorySave(BSkyBlock.getPlugin()); + private HashMap inventories; + + /** + * Saves the inventory of a player + */ + public InventorySave(BSkyBlock plugin) { + inventories = new HashMap(); + } + + /** Save player's inventory + * @param player + */ + public void savePlayerInventory(Player player) { + //plugin.getLogger().info("DEBUG: Saving inventory"); + // Save the player's armor and things + inventories.put(player.getUniqueId(),new InventoryStore(player.getInventory().getContents(), player.getInventory().getArmorContents())); + } + + /** + * Clears any saved inventory + * @param player + */ + public void clearSavedInventory(Player player) { + //plugin.getLogger().info("DEBUG: Clearing inventory"); + inventories.remove(player.getUniqueId()); + } + /** + * Load the player's inventory + * + * @param player + */ + public void loadPlayerInventory(Player player) { + //plugin.getLogger().info("DEBUG: Loading inventory"); + // Get the info for this player + if (inventories.containsKey(player.getUniqueId())) { + InventoryStore inv = inventories.get(player.getUniqueId()); + //plugin.getLogger().info("DEBUG: player is known"); + player.getInventory().setContents(inv.getInventory()); + player.getInventory().setArmorContents(inv.getArmor()); + inventories.remove(player.getUniqueId()); + return; + } + } + + public static InventorySave getInstance() { + return instance; + } + +} diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/InventoryStore.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/InventoryStore.java new file mode 100644 index 000000000..e91fde830 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/InventoryStore.java @@ -0,0 +1,52 @@ +package us.tastybento.bskyblock.listeners.protection; + +import org.bukkit.inventory.ItemStack; + +/** + * Where the inventory data is stored + * + * @author tastybento + */ +public class InventoryStore { + private ItemStack[] inventory; + private ItemStack[] armor; + + /** + * @param inventory + * @param armor + */ + public InventoryStore(ItemStack[] inventory, ItemStack[] armor) { + this.inventory = inventory; + this.armor = armor; + } + + /** + * @return the inventory + */ + public ItemStack[] getInventory() { + return inventory; + } + + /** + * @param inventory + * the inventory to set + */ + public void setInventory(ItemStack[] inventory) { + this.inventory = inventory; + } + + /** + * @return the armor + */ + public ItemStack[] getArmor() { + return armor; + } + + /** + * @param armor + * the armor to set + */ + public void setArmor(ItemStack[] armor) { + this.armor = armor; + } +} diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard.java new file mode 100644 index 000000000..e8f017447 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard.java @@ -0,0 +1,2663 @@ +package us.tastybento.bskyblock.listeners.protection; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World.Environment; +import org.bukkit.block.Biome; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Enderman; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Golem; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Snowman; +import org.bukkit.entity.Squid; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockDispenseEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.PlayerLeashEntityEvent; +import org.bukkit.event.entity.PotionSplashEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; +import org.bukkit.event.inventory.CraftItemEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerEggThrowEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerShearEntityEvent; +import org.bukkit.event.player.PlayerUnleashEntityEvent; +import org.bukkit.event.vehicle.VehicleDamageEvent; +import org.bukkit.event.vehicle.VehicleMoveEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.MaterialData; +import org.bukkit.potion.Potion; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.Vector; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.events.island.IslandEnterEvent; +import us.tastybento.bskyblock.api.events.island.IslandExitEvent; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; +import us.tastybento.bskyblock.generators.IslandWorld; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +/** + * @author tastybento + * Provides protection to islands + */ +@SuppressWarnings("deprecation") +public class IslandGuard implements Listener { + private final BSkyBlock plugin; + private final static boolean DEBUG = false; + private static final boolean DEBUG2 = false; + private HashMap onPlate = new HashMap(); + private Set tntBlocks = new HashSet(); + private Set litCreeper = new HashSet(); + + public IslandGuard(final BSkyBlock plugin) { + this.plugin = plugin; + + } + + + /** + * Prevents visitors picking items from riding horses or other inventories + * @param event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onHorseInventoryClick(InventoryClickEvent event) { + if (DEBUG) + plugin.getLogger().info("DEBUG: horse and llama inventory click"); + if (event.getInventory().getHolder() == null) { + return; + } + // World check + if (!Util.inWorld(event.getWhoClicked())) { + return; + } + if (event.getInventory().getHolder() instanceof Animals) { + if (actionAllowed((Player)event.getWhoClicked(), event.getWhoClicked().getLocation(), SettingsFlag.MOUNT_INVENTORY)) { + return; + } + // Elsewhere - not allowed + Util.sendMessage(event.getWhoClicked(), ChatColor.RED + plugin.getLocale(event.getWhoClicked().getUniqueId()).get("island.protected")); + event.setCancelled(true); + return; + } + } + + /** + * Checks if action is allowed for player in location for flag + * @param player + * @param location + * @param flag + * @return true if allowed + */ + private boolean actionAllowed(Player player, Location location, SettingsFlag flag) { + if (player == null) { + return actionAllowed(location, flag); + } + // This permission bypasses protection + if (player.isOp() || VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) { + return true; + } + Island island = plugin.getIslands().getProtectedIslandAt(location); + if (island != null && (island.getFlag(flag) || island.getMembers().contains(player.getUniqueId()))){ + return true; + } + if (island == null && Settings.defaultWorldSettings.get(flag)) { + return true; + } + return false; + } + + /** + * Action allowed in this location + * @param location + * @param flag + * @return true if allowed + */ + private boolean actionAllowed(Location location, SettingsFlag flag) { + Island island = plugin.getIslands().getProtectedIslandAt(location); + if (island != null && island.getFlag(flag)){ + return true; + } + if (island == null && Settings.defaultWorldSettings.get(flag)) { + return true; + } + return false; + } + + /* + * For testing only + * @EventHandler() + * void testEvent(ChallengeLevelCompleteEvent e) { + * plugin.getLogger().info(e.getEventName()); + * plugin.getLogger().info("DEBUG: challenge level complete!"); + * } + * @EventHandler() + * void testEvent(ChallengeCompleteEvent e) { + * plugin.getLogger().info(e.getEventName()); + * plugin.getLogger().info("DEBUG: challenge complete!"); + * } + */ + // Vehicle damage + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onVehicleDamageEvent(VehicleDamageEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info(e.getAttacker().getType().toString()); + } + if (Util.inWorld(e.getVehicle())) { + if (!(e.getAttacker() instanceof Player)) { + return; + } + Player p = (Player) e.getAttacker(); + if (actionAllowed(p, e.getVehicle().getLocation(), SettingsFlag.BREAK_BLOCKS)) { + return; + } + // Not allowed + Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onVehicleMove(final VehicleMoveEvent e) { + if (DEBUG) + plugin.getLogger().info("DEBUG: vehicle move = " + e.getVehicle()); + if (!Util.inWorld(e.getVehicle())) { + return; + } + + + Entity passenger = e.getVehicle().getPassenger(); + if (passenger == null || !(passenger instanceof Player)) { + return; + } + + Player player = (Player)passenger; + if (plugin.getIslands() == null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: grid = null"); + return; + } + Island islandTo = plugin.getIslands().getProtectedIslandAt(e.getTo()); + // Announcement entering + Island islandFrom = plugin.getIslands().getProtectedIslandAt(e.getFrom()); + // Only says something if there is a change in islands + /* + * Situations: + * islandTo == null && islandFrom != null - exit + * islandTo == null && islandFrom == null - nothing + * islandTo != null && islandFrom == null - enter + * islandTo != null && islandFrom != null - same PlayerIsland or teleport? + * islandTo == islandFrom + */ + // plugin.getLogger().info("islandTo = " + islandTo); + // plugin.getLogger().info("islandFrom = " + islandFrom); + + if (islandTo != null && (islandTo.getOwner() != null || islandTo.isSpawn())) { + // Lock check + if (islandTo.isLocked() || plugin.getPlayers().isBanned(islandTo.getOwner(),player.getUniqueId())) { + if (!islandTo.getMembers().contains(player.getUniqueId()) && !player.isOp() + && !VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect") + && !VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypasslock")) { + Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player.getUniqueId()).get("lock.islandlocked")); + // Get the vector away from this island + Vector v = e.getVehicle().getLocation().toVector().subtract(islandTo.getCenter().toVector()).normalize().multiply(new Vector(1.2,0,1.2)); + if (DEBUG) + plugin.getLogger().info("DEBUG: direction vector = " + v); + e.getVehicle().setVelocity(v); + return; + } + } + } + if (islandTo !=null && islandFrom == null && (islandTo.getOwner() != null || islandTo.isSpawn())) { + // Entering + if (islandTo.isSpawn()) { + if (!plugin.getLocale(player.getUniqueId()).get("lock.enteringspawn").isEmpty()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.enteringspawn")); + } + } + } else { + if (!plugin.getLocale(player.getUniqueId()).get("lock.nowentering").isEmpty()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.nowentering").replace("[name]", plugin.getIslands().getIslandName(islandTo.getOwner()))); + } + } + } + } else if (islandTo == null && islandFrom != null && (islandFrom.getOwner() != null || islandFrom.isSpawn())) { + // Leaving + if (islandFrom.isSpawn()) { + // Leaving + if (!plugin.getLocale(player.getUniqueId()).get("lock.leavingspawn").isEmpty()) { + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.leavingspawn")); + } + } + } else { + if (!plugin.getLocale(player.getUniqueId()).get("lock.nowleaving").isEmpty()) { + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.nowleaving").replace("[name]", plugin.getIslands().getIslandName(islandFrom.getOwner()))); + } + } + } + } else if (islandTo != null && islandFrom !=null && !islandTo.equals(islandFrom)) { + // Adjacent islands or overlapping protections + if (islandFrom.isSpawn()) { + // Leaving + if (!plugin.getLocale(player.getUniqueId()).get("lock.leavingspawn").isEmpty()) { + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.leavingspawn")); + } + } + } else if (islandFrom.getOwner() != null){ + if (!plugin.getLocale(player.getUniqueId()).get("lock.nowleaving").isEmpty()) { + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.nowleaving").replace("[name]", plugin.getIslands().getIslandName(islandFrom.getOwner()))); + } + } + } + if (islandTo.isSpawn()) { + if (!plugin.getLocale(player.getUniqueId()).get("lock.enteringspawn").isEmpty()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.enteringspawn")); + } + } + } else if (islandTo.getOwner() != null) { + if (!plugin.getLocale(player.getUniqueId()).get("lock.nowentering").isEmpty()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(player, plugin.getLocale(player.getUniqueId()).get("lock.nowentering").replace("[name]", plugin.getIslands().getIslandName(islandTo.getOwner()))); + } + } + } + } + } + + + /** + * Adds island lock function + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerMove(final PlayerMoveEvent e) { + if (e.getPlayer().isDead()) { + return; + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + if (plugin.getIslands() == null) { + return; + } + // Only do something if there is a definite x or z movement + if (e.getTo().getBlockX() - e.getFrom().getBlockX() == 0 && e.getTo().getBlockZ() - e.getFrom().getBlockZ() == 0) { + return; + } + final Island islandTo = plugin.getIslands().getProtectedIslandAt(e.getTo()); + // Announcement entering + final Island islandFrom = plugin.getIslands().getProtectedIslandAt(e.getFrom()); + // Only says something if there is a change in islands + /* + * Situations: + * islandTo == null && islandFrom != null - exit + * islandTo == null && islandFrom == null - nothing + * islandTo != null && islandFrom == null - enter + * islandTo != null && islandFrom != null - same PlayerIsland or teleport? + * islandTo == islandFrom + */ + // plugin.getLogger().info("islandTo = " + islandTo); + // plugin.getLogger().info("islandFrom = " + islandFrom); + if (islandTo != null && (islandTo.getOwner() != null || islandTo.isSpawn())) { + // Lock check + if (islandTo.isLocked() || plugin.getPlayers().isBanned(islandTo.getOwner(),e.getPlayer().getUniqueId())) { + if (!islandTo.getMembers().contains(e.getPlayer().getUniqueId()) && !e.getPlayer().isOp() + && !VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + && !VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypasslock")) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.islandlocked")); + + // Get the vector away from this island + if (e.getPlayer().isInsideVehicle()) { + if (e.getPlayer().getVehicle() instanceof LivingEntity) { + // Dismount + e.getPlayer().leaveVehicle(); + e.setCancelled(true); + } + + } else { + Vector v = e.getPlayer().getLocation().toVector().subtract(islandTo.getCenter().toVector()).normalize().multiply(new Vector(1.2,0,1.2)); + if (DEBUG) + plugin.getLogger().info("DEBUG: direction vector = " + v); + e.getPlayer().setVelocity(v); + } + return; + } + } + } + + if (islandTo != null && islandFrom == null && (islandTo.getOwner() != null || islandTo.isSpawn())) { + // Entering + if (islandTo.isLocked() || plugin.getPlayers().isBanned(islandTo.getOwner(),e.getPlayer().getUniqueId())) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.islandlocked")); + } + if (islandTo.isSpawn()) { + if (!plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.enteringspawn").isEmpty()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.enteringspawn")); + } + } + } else { + if (!plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.nowentering").isEmpty()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.nowentering").replace("[name]", plugin.getIslands().getIslandName(islandTo.getOwner()))); + } + } + } + // Fire entry event + final IslandEnterEvent event = new IslandEnterEvent(islandTo, e.getPlayer().getUniqueId(), e.getTo()); + plugin.getServer().getPluginManager().callEvent(event); + } else if (islandTo == null && islandFrom != null && (islandFrom.getOwner() != null || islandFrom.isSpawn())) { + // Leaving + if (islandFrom.isSpawn()) { + // Leaving + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.leavingspawn")); + } + } else { + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.nowleaving").replace("[name]", plugin.getIslands().getIslandName(islandFrom.getOwner()))); } + } + // Fire exit event + final IslandExitEvent event = new IslandExitEvent(islandFrom, e.getPlayer().getUniqueId(), e.getFrom()); + plugin.getServer().getPluginManager().callEvent(event); + } else if (islandTo != null && islandFrom != null && !islandTo.equals(islandFrom)) { + // Adjacent islands or overlapping protections + if (islandFrom.isSpawn()) { + // Leaving + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.leavingspawn")); + } + } else if (islandFrom.getOwner() != null) { + if(islandFrom.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.nowleaving").replace("[name]", plugin.getIslands().getIslandName(islandFrom.getOwner()))); + } + } + if (islandTo.isSpawn()) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.enteringspawn")); + } + } else if (islandTo.getOwner() != null) { + if(islandTo.getFlag(SettingsFlag.ENTER_EXIT_MESSAGES)) { + Util.sendEnterExit(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("lock.nowentering").replace("[name]", plugin.getIslands().getIslandName(islandTo.getOwner()))); + } + } + // Fire exit event + final IslandExitEvent event = new IslandExitEvent(islandFrom, e.getPlayer().getUniqueId(), e.getFrom()); + plugin.getServer().getPluginManager().callEvent(event); + // Fire entry event + final IslandEnterEvent event2 = new IslandEnterEvent(islandTo, e.getPlayer().getUniqueId(), e.getTo()); + plugin.getServer().getPluginManager().callEvent(event2); + } + } + + + /** + * Prevents mobs spawning at spawn or in an island + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onMobSpawn(final CreatureSpawnEvent e) { + if (DEBUG2) { + plugin.getLogger().info("on Mob spawn" + e.getEventName()); + } + // if grid is not loaded yet, return. + if (plugin.getIslands() == null) { + return; + } + // If not in the right world, return + if (!Util.inWorld(e.getEntity())) { + return; + } + // Deal with natural spawning + if (e.getEntity() instanceof Monster || e.getEntity() instanceof Slime) { + if (!actionAllowed(e.getLocation(), SettingsFlag.MONSTER_SPAWN)) { + if (DEBUG2) + plugin.getLogger().info("Natural monster spawn cancelled."); + // Mobs not allowed to spawn + e.setCancelled(true); + return; + } + } + if (e.getEntity() instanceof Animals) { + if (!actionAllowed(e.getLocation(), SettingsFlag.ANIMAL_SPAWN)) { + // Animals are not allowed to spawn + if (DEBUG2) + plugin.getLogger().info("Natural animal spawn cancelled."); + e.setCancelled(true); + return; + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onExplosion(final EntityExplodeEvent e) { + if (DEBUG) { + // Commented out due to Ender dragon spam in Paper Spigot + //plugin.getLogger().info(e.getEventName()); + //plugin.getLogger().info("Entity exploding is " + e.getEntity()); + } + if (!Util.inWorld(e.getLocation())) { + return; + } + // Find out what is exploding + Entity expl = e.getEntity(); + if (expl == null) { + // This allows beds to explode or other null entities, but still curtail the damage + // Note player can still die from beds exploding in the nether. + if (!Settings.allowTNTDamage) { + //plugin.getLogger().info("TNT block damage prevented"); + e.blockList().clear(); + } else { + if (!Settings.allowChestDamage) { + List toberemoved = new ArrayList(); + // Save the chest blocks in a list + for (Block b : e.blockList()) { + switch (b.getType()) { + case CHEST: + case ENDER_CHEST: + case STORAGE_MINECART: + case TRAPPED_CHEST: + toberemoved.add(b); + break; + default: + break; + } + } + // Now delete them + for (Block b : toberemoved) { + e.blockList().remove(b); + } + } + } + return; + } + // prevent at spawn + if (plugin.getIslands().isAtSpawn(e.getLocation())) { + e.setCancelled(true); + } + // Find out what is exploding + EntityType exploding = e.getEntityType(); + if (exploding == null) { + return; + } + switch (exploding) { + case CREEPER: + if (!Settings.allowCreeperDamage) { + // plugin.getLogger().info("Creeper block damage prevented"); + e.blockList().clear(); + } else { + // Check if creeper griefing is allowed + if (!Settings.allowCreeperGriefing) { + // Find out who the creeper was targeting + Creeper creeper = (Creeper)e.getEntity(); + if (creeper.getTarget() instanceof Player) { + Player target = (Player)creeper.getTarget(); + // Check if the target is on their own island or not + if (!plugin.getIslands().locationIsOnIsland(target, e.getLocation())) { + // They are a visitor tsk tsk + // Stop the blocks from being damaged, but allow hurt still + e.blockList().clear(); + } + } + // Check if this creeper was lit by a visitor + if (litCreeper.contains(creeper.getUniqueId())) { + if (DEBUG) { + plugin.getLogger().info("DBEUG: preventing creeper from damaging"); + } + litCreeper.remove(creeper.getUniqueId()); + e.setCancelled(true); + return; + } + } + if (!Settings.allowChestDamage) { + List toberemoved = new ArrayList(); + // Save the chest blocks in a list + for (Block b : e.blockList()) { + switch (b.getType()) { + case CHEST: + case ENDER_CHEST: + case STORAGE_MINECART: + case TRAPPED_CHEST: + toberemoved.add(b); + break; + default: + break; + } + } + // Now delete them + for (Block b : toberemoved) { + e.blockList().remove(b); + } + } + } + break; + case PRIMED_TNT: + case MINECART_TNT: + if (!Settings.allowTNTDamage) { + // plugin.getLogger().info("TNT block damage prevented"); + e.blockList().clear(); + } else { + if (!Settings.allowChestDamage) { + List toberemoved = new ArrayList(); + // Save the chest blocks in a list + for (Block b : e.blockList()) { + switch (b.getType()) { + case CHEST: + case ENDER_CHEST: + case STORAGE_MINECART: + case TRAPPED_CHEST: + toberemoved.add(b); + break; + default: + break; + } + } + // Now delete them + for (Block b : toberemoved) { + e.blockList().remove(b); + } + } + } + break; + default: + break; + } + } + + /** + * Allows or prevents enderman griefing + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEndermanGrief(final EntityChangeBlockEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!(e.getEntity() instanceof Enderman)) { + return; + } + if (!Util.inWorld(e.getEntity())) { + return; + } + // Prevent Enderman griefing at spawn + if (plugin.getIslands() != null && plugin.getIslands().isAtSpawn(e.getEntity().getLocation())) { + e.setCancelled(true); + } + if (Settings.allowEndermanGriefing) + return; + // Stop the Enderman from griefing + // plugin.getLogger().info("Enderman stopped from griefing); + e.setCancelled(true); + } + + /** + * Drops the Enderman's block when he dies if he has one + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEndermanDeath(final EntityDeathEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Settings.endermanDeathDrop) + return; + if (!Util.inWorld(e.getEntity())) { + return; + } + if (!(e.getEntity() instanceof Enderman)) { + // plugin.getLogger().info("Not an Enderman!"); + return; + } + // Get the block the enderman is holding + Enderman ender = (Enderman) e.getEntity(); + MaterialData m = ender.getCarriedMaterial(); + if (m != null && !m.getItemType().equals(Material.AIR)) { + // Drop the item + // plugin.getLogger().info("Dropping item " + m.toString()); + e.getEntity().getWorld().dropItemNaturally(e.getEntity().getLocation(), m.toItemStack(1)); + } + } + + /* + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false) + public void onBlockBreakCheck(final BlockPhysicsEvent e) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: check: " + e.getEventName()); + plugin.getLogger().info("DEBUG: block is " + e.getBlock()); + } + } + */ + + /** + * Prevents blocks from being broken + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockBreak(final BlockBreakEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (Settings.allowAutoActivator && e.getPlayer().getName().equals("[CoFH]")) { + return; + } + if (Util.inWorld(e.getPlayer())) { + if (actionAllowed(e.getPlayer(), e.getBlock().getLocation(), SettingsFlag.BREAK_BLOCKS)) { + return; + } + // Everyone else - not allowed + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onItemFrameDamage(final EntityDamageByEntityEvent e) { + // Check world + if (!Util.inWorld(e.getEntity()) || !(e.getEntity() instanceof ItemFrame)) { + return; + } + if (e.getDamager() instanceof Projectile) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Projectile damage to itemframe"); + // Find out who fired the arrow + Projectile p = (Projectile) e.getDamager(); + if (DEBUG) + plugin.getLogger().info("DEBUG: Shooter is " + p.getShooter().toString()); + if (p.getShooter() instanceof Skeleton || p.getShooter() instanceof Golem) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Shooter is mob"); + if (!Settings.allowMobDamageToItemFrames) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Damage not allowed, cancelling"); + e.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onItemFrameDamage(final HangingBreakByEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: Hanging break by entity event"); + plugin.getLogger().info("DEBUG: cause = " + e.getCause()); + plugin.getLogger().info("DEBUG: entity = " + e.getEntity()); + plugin.getLogger().info("DEBUG: remover = " + e.getRemover()); + } + // Check world + if (!Util.inWorld(e.getEntity()) || !(e.getEntity() instanceof ItemFrame)) { + return; + } + if (e.getRemover() instanceof Skeleton || e.getRemover() instanceof Golem) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Remover is mob"); + if (!Settings.allowMobDamageToItemFrames) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Damage not allowed, cancelling"); + e.setCancelled(true); + } + } + } + /** + * This method protects players from PVP if it is not allowed and from + * arrows fired by other players + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEntityDamage(final EntityDamageByEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info("DEBUG: Damager = " + e.getDamager().toString()); + plugin.getLogger().info("DEBUG: Entitytype = " + e.getEntityType()); + plugin.getLogger().info("DEBUG: Entity = " + e.getEntity()); + } + // Check world + if (!Util.inWorld(e.getEntity())) { + return; + } + // Get the island where the damage is occurring + Island island = plugin.getIslands().getProtectedIslandAt(e.getEntity().getLocation()); + boolean inNether = false; + if (e.getEntity().getWorld().equals(IslandWorld.getNetherWorld())) { + inNether = true; + } + // Stop TNT damage if it is disallowed + if (!Settings.allowTNTDamage && (e.getDamager().getType().equals(EntityType.PRIMED_TNT) + || e.getDamager().getType().equals(EntityType.FIREWORK) + || e.getDamager().getType().equals(EntityType.FIREBALL))) { + if (DEBUG) + plugin.getLogger().info("DEBUG: cancelling firework or fireball damage"); + e.setCancelled(true); + return; + } + // Check for creeper damage at spawn + if (island != null && island.isSpawn() && e.getDamager().getType().equals(EntityType.CREEPER) && island.getFlag(SettingsFlag.CREEPER_HURT)) { + return; + } + // Stop Creeper damager if it is disallowed + if (!Settings.allowCreeperDamage && e.getDamager().getType().equals(EntityType.CREEPER) && !(e.getEntity() instanceof Player)) { + e.setCancelled(true); + return; + } + // Stop Creeper griefing if it is disallowed + if (!Settings.allowCreeperGriefing && e.getDamager().getType().equals(EntityType.CREEPER)) { + // Now we have to check what the target was + Creeper creeper = (Creeper)e.getDamager(); + //plugin.getLogger().info("DEBUG: creeper is damager"); + //plugin.getLogger().info("DEBUG: entity being damaged is " + e.getEntity()); + if (creeper.getTarget() instanceof Player) { + //plugin.getLogger().info("DEBUG: target is a player"); + Player target = (Player)creeper.getTarget(); + //plugin.getLogger().info("DEBUG: player = " + target.getName()); + // Check if the target is on their own island or not + if (!plugin.getIslands().locationIsOnIsland(target, e.getEntity().getLocation())) { + // They are a visitor tsk tsk + //plugin.getLogger().info("DEBUG: player is a visitor"); + e.setCancelled(true); + return; + } + } + // Check if this creeper was lit by a visitor + if (litCreeper.contains(creeper.getUniqueId())) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: preventing creeeper from damaging"); + } + e.setCancelled(true); + return; + } + } + // Ops can do anything + if (e.getDamager() instanceof Player) { + Player p = (Player) e.getDamager(); + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + } + // Get the real attacker + boolean flamingArrow = false; + boolean projectile = false; + Player attacker = null; + if (e.getDamager() instanceof Player) { + attacker = (Player)e.getDamager(); + } else if (e.getDamager() instanceof Projectile) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Projectile damage"); + projectile = true; + // Find out who fired the arrow + Projectile p = (Projectile) e.getDamager(); + if (DEBUG) + plugin.getLogger().info("DEBUG: Shooter is " + p.getShooter().toString()); + if (p.getShooter() instanceof Player) { + attacker = (Player) p.getShooter(); + if (p.getFireTicks() > 0) { + flamingArrow = true; + } + // Check if this is a flaming arrow + if (DEBUG) + plugin.getLogger().info("DEBUG: fire ticks = " + p.getFireTicks() + " max = " + p.getMaxFireTicks()); + } + } + if (attacker == null) { + // Not a player + return; + } + // Self damage + if (e.getEntity() instanceof Player && attacker.equals((Player)e.getEntity())) { + if (DEBUG) plugin.getLogger().info("Self damage!"); + return; + } + if (DEBUG) + plugin.getLogger().info("DEBUG: Another player"); + + // ITEM FRAME ENTITY DAMAGE or Armor Stand + // Check to see if it's an item frame + if (e.getEntity() instanceof ItemFrame || e.getEntityType().toString().endsWith("STAND")) { + if (island != null && (island.getFlag(SettingsFlag.BREAK_BLOCKS) || island.getMembers().contains(attacker.getUniqueId()))) { + return; + } + // Else not allowed + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("island.protected")); + if (flamingArrow) + e.getEntity().setFireTicks(0); + if (projectile) + e.getDamager().remove(); + e.setCancelled(true); + return; + } + // Monsters being hurt + if (e.getEntity() instanceof Monster || e.getEntity() instanceof Slime || e.getEntity() instanceof Squid) { + // Normal island check + if (island != null && island.getMembers().contains(attacker.getUniqueId())) { + // Members always allowed + return; + } + if (actionAllowed(attacker, e.getEntity().getLocation(), SettingsFlag.HURT_MONSTERS)) { + // Check for visitors setting creepers alight using flint steel + if (!Settings.allowCreeperGriefing && e.getEntity() instanceof Creeper) { + for (ItemStack holding : Util.getPlayerInHandItems(attacker)) { + if (holding.getType().equals(Material.FLINT_AND_STEEL)) { + // Save this creeper for later when any damage caused by its explosion will be nullified + litCreeper.add(e.getEntity().getUniqueId()); + if (DEBUG) { + plugin.getLogger().info("DEBUG: adding to lit creeper set"); + } + } + } + } + return; + } + // Not allowed + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("island.protected")); + if (flamingArrow) + e.getEntity().setFireTicks(0); + if (projectile) + e.getDamager().remove(); + e.setCancelled(true); + return; + } + + // Mobs being hurt + if (e.getEntity() instanceof Animals || e.getEntity() instanceof IronGolem || e.getEntity() instanceof Snowman + || e.getEntity() instanceof Villager) { + if (island != null && (island.getFlag(SettingsFlag.HURT_ANIMALS) || island.getMembers().contains(attacker.getUniqueId()))) { + return; + } + if (DEBUG) + plugin.getLogger().info("DEBUG: Mobs not allowed to be hurt. Blocking"); + // Else not allowed + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("island.protected")); + if (flamingArrow) + e.getEntity().setFireTicks(0); + if (projectile) + e.getDamager().remove(); + e.setCancelled(true); + return; + } + + // Establish whether PVP is allowed or not. + boolean pvp = false; + if ((inNether && island != null && island.getFlag(SettingsFlag.PVP_NETHER) || (!inNether && island != null && island.getFlag(SettingsFlag.PVP_OVERWORLD)))) { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed"); + pvp = true; + } + + // Players being hurt PvP + if (e.getEntity() instanceof Player) { + if (pvp) { + return; + } else { + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("targetInPVPArea")); + if (flamingArrow) + e.getEntity().setFireTicks(0); + if (projectile) + e.getDamager().remove(); + e.setCancelled(true); + return; + } + } + } + + /** + * Prevents placing of blocks + * + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerBlockPlace(final BlockPlaceEvent e) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: " + e.getEventName()); + if (e.getPlayer() == null) { + plugin.getLogger().info("DEBUG: player is null"); + } else { + plugin.getLogger().info("DEBUG: block placed by " + e.getPlayer().getName()); + } + plugin.getLogger().info("DEBUG: Block is " + e.getBlock().toString()); + } + if (Settings.allowAutoActivator && e.getPlayer().getName().equals("[CoFH]")) { + return; + } + // plugin.getLogger().info(e.getEventName()); + if (Util.inWorld(e.getPlayer())) { + // This permission bypasses protection + if (e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + //plugin.getLogger().info("DEBUG: checking is inside protection area"); + Island island = plugin.getIslands().getProtectedIslandAt(e.getBlock().getLocation()); + // Outside of island protection zone + if (island == null) { + if (!Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } + if (actionAllowed(e.getPlayer(), e.getBlock().getLocation(), SettingsFlag.PLACE_BLOCKS)) { + // Check how many placed + //plugin.getLogger().info("DEBUG: block placed " + e.getBlock().getType()); + String type = e.getBlock().getType().toString(); + if (!e.getBlock().getState().getClass().getName().endsWith("CraftBlockState") + // Not all blocks have that type of class, so we have to do some explicit checking... + || e.getBlock().getType().equals(Material.REDSTONE_COMPARATOR_OFF) + || type.endsWith("BANNER") // Avoids V1.7 issues + || e.getBlock().getType().equals(Material.ENDER_CHEST) + || e.getBlock().getType().equals(Material.ENCHANTMENT_TABLE) + || e.getBlock().getType().equals(Material.DAYLIGHT_DETECTOR) + || e.getBlock().getType().equals(Material.FLOWER_POT)){ + // tile entity placed + if (Settings.limitedBlocks.containsKey(type) && Settings.limitedBlocks.get(type) > -1) { + int count = island.getTileEntityCount(e.getBlock().getType(),e.getBlock().getWorld()); + //plugin.getLogger().info("DEBUG: count is "+ count); + if (Settings.limitedBlocks.get(type) <= count) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]", + Util.prettifyText(type))).replace("[number]", String.valueOf(Settings.limitedBlocks.get(type)))); + e.setCancelled(true); + return; + } + } + } + } else { + // Visitor + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerBlockPlace(final BlockMultiPlaceEvent e) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: " + e.getEventName()); + if (e.getPlayer() == null) { + plugin.getLogger().info("DEBUG: player is null"); + } else { + plugin.getLogger().info("DEBUG: block placed by " + e.getPlayer().getName()); + } + plugin.getLogger().info("DEBUG: Block is " + e.getBlock().toString()); + } + if (Settings.allowAutoActivator && e.getPlayer().getName().equals("[CoFH]")) { + return; + } + // plugin.getLogger().info(e.getEventName()); + if (Util.inWorld(e.getPlayer())) { + // This permission bypasses protection + if (e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + Island island = plugin.getIslands().getProtectedIslandAt(e.getBlock().getLocation()); + if (island == null) { + if (!Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } + // Island exists + if (island.getFlag(SettingsFlag.PLACE_BLOCKS) || island.getMembers().contains(e.getPlayer().getUniqueId())) { + // Check how many placed + //plugin.getLogger().info("DEBUG: block placed " + e.getBlock().getType()); + String type = e.getBlock().getType().toString(); + if (!e.getBlock().getState().getClass().getName().endsWith("CraftBlockState") + // Not all blocks have that type of class, so we have to do some explicit checking... + || e.getBlock().getType().equals(Material.REDSTONE_COMPARATOR_OFF) + || type.endsWith("BANNER") // Avoids V1.7 issues + || e.getBlock().getType().equals(Material.ENDER_CHEST) + || e.getBlock().getType().equals(Material.ENCHANTMENT_TABLE) + || e.getBlock().getType().equals(Material.DAYLIGHT_DETECTOR) + || e.getBlock().getType().equals(Material.FLOWER_POT)){ + // tile entity placed + if (Settings.limitedBlocks.containsKey(type) && Settings.limitedBlocks.get(type) > -1) { + int count = island.getTileEntityCount(e.getBlock().getType(),e.getBlock().getWorld()); + if (Settings.limitedBlocks.get(type) <= count) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]", + Util.prettifyText(type))).replace("[number]", String.valueOf(Settings.limitedBlocks.get(type)))); + e.setCancelled(true); + return; + } + } + } + return; + } + // Outside of protection area or visitor + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerLeashHitch(final HangingPlaceEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info("DEBUG: block placed " + e.getBlock().getType()); + plugin.getLogger().info("DEBUG: entity " + e.getEntity().getType()); + } + if (Settings.allowAutoActivator && e.getPlayer().getName().equals("[CoFH]")) { + return; + } + // plugin.getLogger().info(e.getEventName()); + if (Util.inWorld(e.getPlayer())) { + if (e.getEntity() != null && e.getEntity().getType().equals(EntityType.LEASH_HITCH)) { + if (!actionAllowed(e.getPlayer(), e.getBlock().getLocation(), SettingsFlag.LEASH)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + } + } + + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerBlockPlace(final HangingPlaceEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info("DEBUG: block placed " + e.getBlock().getType()); + plugin.getLogger().info("DEBUG: entity " + e.getEntity().getType()); + } + if (Settings.allowAutoActivator && e.getPlayer().getName().equals("[CoFH]")) { + return; + } + // plugin.getLogger().info(e.getEventName()); + if (Util.inWorld(e.getPlayer())) { + // This permission bypasses protection + if (e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + Island island = plugin.getIslands().getProtectedIslandAt(e.getBlock().getLocation()); + // Outside of island protection zone + if (island == null) { + if (!Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } + if (island.getFlag(SettingsFlag.PLACE_BLOCKS) || island.getMembers().contains(e.getPlayer().getUniqueId())) { + // Check how many placed + String type = e.getEntity().getType().toString(); + if (e.getEntity().getType().equals(EntityType.ITEM_FRAME) || e.getEntity().getType().equals(EntityType.PAINTING)) { + // tile entity placed + if (Settings.limitedBlocks.containsKey(type) && Settings.limitedBlocks.get(type) > -1) { + // Convert from EntityType to Material via string - ugh + int count = island.getTileEntityCount(Material.valueOf(type),e.getEntity().getWorld()); + if (Settings.limitedBlocks.get(type) <= count) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]", + Util.prettifyText(type))).replace("[number]", String.valueOf(Settings.limitedBlocks.get(type)))); + e.setCancelled(true); + return; + } + } + } + } else { + // Visitor + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + } + + // Prevent sleeping in other beds + @EventHandler(priority = EventPriority.LOW) + public void onPlayerBedEnter(final PlayerBedEnterEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + // Check world + if (Util.inWorld(e.getPlayer())) { + if (actionAllowed(e.getPlayer(),e.getBed().getLocation(), SettingsFlag.BED)) { + return; + } + // Not allowed + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + + /** + * Prevents the breakage of hanging items + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onBreakHanging(final HangingBreakByEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info(e.getRemover().toString()); + } + if (Util.inWorld(e.getEntity())) { + if ((e.getRemover() instanceof Creeper) && !Settings.allowCreeperDamage) { + e.setCancelled(true); + return; + } + // Check if creeper griefing is allowed + if ((e.getRemover() instanceof Creeper) && !Settings.allowCreeperGriefing) { + // Find out who the creeper was targeting + Creeper creeper = (Creeper)e.getRemover(); + if (creeper.getTarget() instanceof Player) { + Player target = (Player)creeper.getTarget(); + // Check if the target is on their own island or not + if (!plugin.getIslands().locationIsOnIsland(target, e.getEntity().getLocation())) { + // They are a visitor tsk tsk + e.setCancelled(true); + return; + } + } + // Check if this creeper was lit by a visitor + if (litCreeper.contains(creeper.getUniqueId())) { + if (DEBUG) { + plugin.getLogger().info("DBEUG: preventing creeper from damaging"); + } + e.setCancelled(true); + return; + } + } + if (e.getRemover() instanceof Player) { + Player p = (Player) e.getRemover(); + // This permission bypasses protection + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + if (actionAllowed(p,e.getEntity().getLocation(),SettingsFlag.BREAK_BLOCKS)) { + return; + } + // Not allowed + Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + } + + /** + * Prevents the leash use + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onLeashUse(final PlayerLeashEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (Util.inWorld(e.getEntity())) { + if (e.getPlayer() != null) { + Player player = e.getPlayer(); + if (actionAllowed(player, e.getEntity().getLocation(),SettingsFlag.LEASH)) { + return; + } + Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + } + + + /** + * Prevents the leash use + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onLeashUse(final PlayerUnleashEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (Util.inWorld(e.getEntity())) { + if (e.getPlayer() != null) { + Player player = e.getPlayer(); + if (actionAllowed(player, e.getEntity().getLocation(),SettingsFlag.LEASH)) { + return; + } + Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + } + /* + * Not going to implement this right now, but it could be used if required + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onLiquidFlow(final BlockFromToEvent e) { + // Ignore non-island worlds + if (!Util.inWorld(e.getBlock())) { + return; + } + // Only check lateral movement + if (e.getBlock().getLocation().getBlockX() == e.getToBlock().getLocation().getBlockX() + && e.getBlock().getLocation().getBlockZ() == e.getToBlock().getLocation().getBlockZ()) { + return; + } + // Ignore flows within flow + if (e.getBlock().getType().equals(e.getToBlock().getType())) { + return; + } + // Ignore stationary to non-stationary + if (e.getBlock().getType().equals(Material.STATIONARY_WATER) && e.getToBlock().getType().equals(Material.WATER) ) { + return; + } + if (e.getBlock().getType().equals(Material.STATIONARY_LAVA) && e.getToBlock().getType().equals(Material.LAVA) ) { + return; + } + // Check if flow leaving island protection range + // Check home island + Island from = plugin.getIslands().getProtectedIslandAt(e.getBlock().getLocation()); + Island to = plugin.getIslands().getProtectedIslandAt(e.getToBlock().getLocation()); + // Scenarios + // 1. inside district or outside - always ok + // 2. inside to outside - not allowed + // 3. outside to inside - allowed + if (to == null && from == null) { + return; + } + if (to !=null && from != null && to.equals(from)) { + return; + } + // Flows into an island space is allowed, e.g., sea + if (to != null) { + return; + } + // Otherwise cancel - the flow is not allowed + e.setCancelled(true); + } + */ + + /** + * Prevents emptying of buckets outside of island space + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBucketEmpty(final PlayerBucketEmptyEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (Util.inWorld(e.getPlayer())) { + Player p = e.getPlayer(); + if (e.getBlockClicked() != null) { + // This is where the water or lava actually will be dumped + Block dumpBlock = e.getBlockClicked().getRelative(e.getBlockFace()); + if (actionAllowed(p, dumpBlock.getLocation(), SettingsFlag.BUCKET)) { + // Check if biome is Nether and then allow water placement but fizz the water + if (e.getBlockClicked().getBiome().equals(Biome.HELL)) { + if (plugin.getServer().getVersion().contains("(MC: 1.8") || plugin.getServer().getVersion().contains("(MC: 1.7")) { + if (e.getPlayer().getItemInHand().getType().equals(Material.WATER_BUCKET)) { + e.setCancelled(true); + e.getPlayer().getItemInHand().setType(Material.BUCKET); + e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.valueOf("FIZZ"), 1F, 2F); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("biome.set").replace("[biome]", "Nether")); + } + } else { + if (Util.playerIsHolding(e.getPlayer(), Material.WATER_BUCKET)) { + e.setCancelled(true); + if (e.getPlayer().getInventory().getItemInMainHand().getType() == Material.WATER_BUCKET) { + e.getPlayer().getInventory().setItemInMainHand(new ItemStack(Material.BUCKET)); + } else if (e.getPlayer().getInventory().getItemInOffHand().getType() == Material.WATER_BUCKET) { + e.getPlayer().getInventory().setItemInOffHand(new ItemStack(Material.BUCKET)); + } + e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1F, 2F); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("biome.set").replace("[biome]", "Nether")); + } + } + } + return; + } + // Not allowed + Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + } + + /** + * Prevents water from being dispensed in hell biomes + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onNetherDispenser(final BlockDispenseEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Util.inWorld(e.getBlock().getLocation()) || !e.getBlock().getBiome().equals(Biome.HELL)) { + return; + } + // plugin.getLogger().info("DEBUG: Item being dispensed is " + + // e.getItem().getType().toString()); + if (e.getItem().getType().equals(Material.WATER_BUCKET)) { + e.setCancelled(true); + if (plugin.getServer().getVersion().contains("(MC: 1.8") || plugin.getServer().getVersion().contains("(MC: 1.7")) { + e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.valueOf("FIZZ"), 1F, 2F); + } else { + e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1F, 2F); + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onBucketFill(final PlayerBucketFillEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (Util.inWorld(e.getPlayer())) { + // This permission bypasses protection + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + Island island = plugin.getIslands().getProtectedIslandAt(e.getBlockClicked().getLocation()); + if (island != null) { + if (island.getMembers().contains(e.getPlayer().getUniqueId())) { + return; + } + if (island.getFlag(SettingsFlag.COLLECT_LAVA) && e.getItemStack().getType().equals(Material.LAVA_BUCKET)) { + return; + } + if (island.getFlag(SettingsFlag.COLLECT_WATER) && e.getItemStack().getType().equals(Material.WATER_BUCKET)) { + return; + } + if (island.getFlag(SettingsFlag.MILKING) && e.getItemStack().getType().equals(Material.MILK_BUCKET)) { + return; + } + if (island.getFlag(SettingsFlag.BUCKET)) { + return; + } + } else { + // Null + if (Settings.defaultWorldSettings.get(SettingsFlag.BUCKET)) { + return; + } + } + // Not allowed + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + + // Protect sheep + @EventHandler(priority = EventPriority.LOW) + public void onShear(final PlayerShearEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (Util.inWorld(e.getPlayer())) { + if (actionAllowed(e.getPlayer(), e.getEntity().getLocation(), SettingsFlag.SHEARING)) { + return; + } + // Not allowed + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + + /** + * Handles interaction with objects + * + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerInteract(final PlayerInteractEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + if (e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + if ((e.getClickedBlock() != null && plugin.getIslands().locationIsOnIsland(e.getPlayer(), e.getClickedBlock().getLocation()))) { + // You can do anything on your island + return; + } + // Player is not clicking a block, they are clicking a material so this + // is driven by where the player is + if (e.getClickedBlock() == null && (e.getMaterial() != null && plugin.getIslands().playerIsOnIsland(e.getPlayer()))) { + return; + } + // Get island + Island island = plugin.getIslands().getProtectedIslandAt(e.getPlayer().getLocation()); + if (DEBUG) { + if (island == null) { + plugin.getLogger().info("DEBUG: Player is not on a known island."); + } else { + plugin.getLogger().info("DEBUG: Player is on a known island."); + } + } + // Check for disallowed clicked blocks + if (e.getClickedBlock() != null) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: clicked block " + e.getClickedBlock()); + plugin.getLogger().info("DEBUG: Material " + e.getMaterial()); + } + // Look along player's sight line to see if any blocks are fire + try { + BlockIterator iter = new BlockIterator(e.getPlayer(), 10); + Block lastBlock = iter.next(); + while (iter.hasNext()) { + lastBlock = iter.next(); + if (DEBUG) + plugin.getLogger().info("DEBUG: lastBlock = " + lastBlock.toString()); + if (lastBlock.equals(e.getClickedBlock())) { + if (DEBUG) + plugin.getLogger().info("DEBUG: found clicked block"); + break; + } + if (lastBlock.getType().equals(Material.FIRE)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: fire found"); + if (island != null) { + if (!island.getFlag(SettingsFlag.FIRE_EXTINGUISH)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } else { + if (Settings.defaultWorldSettings.get(SettingsFlag.FIRE_EXTINGUISH)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: extinguishing is allowed"); + continue; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + } + } + } catch (Exception ex) { + // To catch at block iterator exceptions that can happen in the void or at the very top of blocks + if (DEBUG) { + plugin.getLogger().info("DEBUG: block iterator error"); + ex.printStackTrace(); + } + } + // Handle Shulker Boxes + if (e.getClickedBlock().getType().toString().contains("SHULKER_BOX")) { + if (island == null) { + if (!Settings.defaultWorldSettings.get(SettingsFlag.OPEN_CHESTS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } else if (!island.getFlag(SettingsFlag.OPEN_CHESTS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } + // Handle fireworks + if (e.getMaterial() != null && e.getMaterial().equals(Material.FIREWORK)) { + if (island == null) { + if (!Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } else if (!island.getFlag(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } + if (DEBUG) + plugin.getLogger().info("DEBUG: clicked block = " + e.getClickedBlock().getType()); + switch (e.getClickedBlock().getType()) { + case WOODEN_DOOR: + case SPRUCE_DOOR: + case ACACIA_DOOR: + case DARK_OAK_DOOR: + case BIRCH_DOOR: + case JUNGLE_DOOR: + case TRAP_DOOR: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.DOOR)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.DOOR)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case FENCE_GATE: + case SPRUCE_FENCE_GATE: + case ACACIA_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case BIRCH_FENCE_GATE: + case JUNGLE_FENCE_GATE: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.GATE)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.GATE)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case ENDER_CHEST: + break; + case CHEST: + case TRAPPED_CHEST: + case DISPENSER: + case DROPPER: + case HOPPER: + case HOPPER_MINECART: + case STORAGE_MINECART: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.OPEN_CHESTS)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.OPEN_CHESTS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case SOIL: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.CROP_TRAMPLE)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.CROP_TRAMPLE)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case BREWING_STAND: + case CAULDRON: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.BREWING)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.BREWING)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case DIODE: + case DIODE_BLOCK_OFF: + case DIODE_BLOCK_ON: + case REDSTONE_COMPARATOR_ON: + case REDSTONE_COMPARATOR_OFF: + case DAYLIGHT_DETECTOR: + case DAYLIGHT_DETECTOR_INVERTED: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.REDSTONE)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.REDSTONE)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case ENCHANTMENT_TABLE: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.ENCHANTING)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.ENCHANTING)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case FURNACE: + case BURNING_FURNACE: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.FURNACE)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.FURNACE)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case ICE: + break; + case ITEM_FRAME: + break; + case JUKEBOX: + if (DEBUG) + plugin.getLogger().info("DEBUG: Jukebox"); + case NOTE_BLOCK: + if (island == null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Jukebox island = null"); + if (Settings.defaultWorldSettings.get(SettingsFlag.MUSIC)) { + return; + } else { + if (DEBUG) + plugin.getLogger().info("DEBUG: Jukebox not allowed"); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.MUSIC)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Jukebox not allowed"); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case PACKED_ICE: + break; + case STONE_BUTTON: + case WOOD_BUTTON: + case LEVER: + if (island == null) { + // TODO: BUTTON? + if (Settings.defaultWorldSettings.get(SettingsFlag.LEVER)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.LEVER)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case TNT: + break; + case WORKBENCH: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.CRAFTING)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.CRAFTING)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case ANVIL: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.ANVIL)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.ANVIL)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case RAILS: + case POWERED_RAIL: + case DETECTOR_RAIL: + case ACTIVATOR_RAIL: + // If they are not on an island, it's protected + if (island == null) { + if (!Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } + if (!island.getFlag(SettingsFlag.PLACE_BLOCKS)) { + if (e.getMaterial() == Material.MINECART || e.getMaterial() == Material.STORAGE_MINECART || e.getMaterial() == Material.HOPPER_MINECART + || e.getMaterial() == Material.EXPLOSIVE_MINECART || e.getMaterial() == Material.POWERED_MINECART) { + e.setCancelled(true); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.getPlayer().updateInventory(); + return; + } + } + case BEACON: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.BEACON)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.BEACON)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case CAKE_BLOCK: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.getPlayer().setFoodLevel(e.getPlayer().getFoodLevel() - 2); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.BREAK_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.getPlayer().setFoodLevel(e.getPlayer().getFoodLevel() - 2); + e.setCancelled(true); + return; + } + break; + case DRAGON_EGG: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.BREAK_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case MOB_SPAWNER: + if (island == null) { + if (Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) { + return; + } else { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + if (!island.getFlag(SettingsFlag.BREAK_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + break; + case BED_BLOCK: + if (e.getPlayer().getWorld().getEnvironment().equals(Environment.NETHER)) { + // Prevent explosions + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + default: + break; + } + } + // Check for disallowed in-hand items + if (DEBUG) { + plugin.getLogger().info("Material = " + e.getMaterial()); + plugin.getLogger().info("in hand = " + Util.getPlayerInHandItems(e.getPlayer())); + } + if (e.getMaterial() != null) { + // This check protects against an exploit in 1.7.9 against cactus + // and sugar cane + if (e.getMaterial() == Material.WOOD_DOOR || e.getMaterial() == Material.CHEST + || e.getMaterial() == Material.TRAPPED_CHEST || e.getMaterial() == Material.IRON_DOOR) { + if ((island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) + || (island !=null && !island.getFlag(SettingsFlag.PLACE_BLOCKS))) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + e.getPlayer().updateInventory(); + return; + } + } else if (e.getMaterial().name().contains("BOAT") && (e.getClickedBlock() != null && !e.getClickedBlock().isLiquid())) { + // Trying to put a boat on non-liquid + if ((island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) + || (island !=null && !island.getFlag(SettingsFlag.PLACE_BLOCKS))) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } else if (e.getMaterial().equals(Material.ENDER_PEARL)) { + if ((island == null && Settings.defaultWorldSettings.get(SettingsFlag.THROW_ENDERPEARLS)) + || (island !=null && !island.getFlag(SettingsFlag.THROW_ENDERPEARLS))) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } else if (e.getMaterial().equals(Material.FLINT_AND_STEEL)) { + plugin.getLogger().info("DEBUG: flint & steel"); + if (e.getClickedBlock() != null) { + if (e.getMaterial().equals(Material.OBSIDIAN)) { + plugin.getLogger().info("DEBUG: flint & steel on obsidian"); + //return; + } + if (!actionAllowed(e.getPlayer(), e.getClickedBlock().getLocation(), SettingsFlag.FIRE)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + return; + } else if (e.getMaterial().equals(Material.MONSTER_EGG)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: allowMonsterEggs = " + island.getFlag(SettingsFlag.SPAWN_EGGS)); + if (!actionAllowed(e.getPlayer(),e.getClickedBlock().getLocation(),SettingsFlag.SPAWN_EGGS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + return; + } else if (e.getMaterial().equals(Material.POTION) && e.getItem().getDurability() != 0) { + // Potion + // plugin.getLogger().info("DEBUG: potion"); + try { + Potion p = Potion.fromItemStack(e.getItem()); + if (p.isSplash()) { + // Splash potions are allowed only if PVP is allowed + boolean inNether = false; + if (e.getPlayer().getWorld().equals(IslandWorld.getNetherWorld())) { + inNether = true; + } + // Check PVP + if (island == null) { + if ((inNether && Settings.defaultWorldSettings.get(SettingsFlag.PVP_NETHER) + || (!inNether && Settings.defaultWorldSettings.get(SettingsFlag.PVP_OVERWORLD)))) { + return; + } + } else { + if ((inNether && island.getFlag(SettingsFlag.PVP_NETHER) || (!inNether && island.getFlag(SettingsFlag.PVP_OVERWORLD)))) { + return; + } + } + // Not allowed + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } catch (Exception ex) { + } + } + // Everything else is okay + } + } + + /** + * Prevents crafting of EnderChest unless the player has permission + * + * @param event + */ + @EventHandler(priority = EventPriority.LOW) + public void onCraft(CraftItemEvent event) { + if (DEBUG) { + plugin.getLogger().info(event.getEventName()); + } + Player player = (Player) event.getWhoClicked(); + if (Util.inWorld(player) || player.getWorld().equals(IslandWorld.getNetherWorld())) { + if (event.getRecipe().getResult().getType() == Material.ENDER_CHEST) { + if (!(player.hasPermission(Settings.PERMPREFIX + "craft.enderchest"))) { + Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player.getUniqueId()).get("general.errors.no-permission")); + event.setCancelled(true); + } + } + } + } + + /** + * Prevents usage of an Ender Chest + * + * @param event + */ + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onEnderChestEvent(PlayerInteractEvent event) { + if (DEBUG) { + plugin.getLogger().info("Ender chest " + event.getEventName()); + } + Player player = (Player) event.getPlayer(); + if (Util.inWorld(player) || player.getWorld().equals(IslandWorld.getNetherWorld())) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (event.getClickedBlock().getType() == Material.ENDER_CHEST) { + if (!(event.getPlayer().hasPermission(Settings.PERMPREFIX + "craft.enderchest"))) { + Util.sendMessage(player, ChatColor.RED + plugin.getLocale(player.getUniqueId()).get("general.errors.no-permission")); + event.setCancelled(true); + } + } + } + } + } + + + /** + * Handles hitting minecarts or feeding animals + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerHitEntity(PlayerInteractEntityEvent e) { + Player p = e.getPlayer(); + if (DEBUG) { + plugin.getLogger().info("Hit entity event " + e.getEventName()); + } + if (!Util.inWorld(p)) { + return; + } + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + // You can do anything if you are Op of have the bypass + return; + } + // Leashes are dealt with elsewhere + if (Util.playerIsHolding(p, Material.LEASH)) { + return; + } + Island island = plugin.getIslands().getProtectedIslandAt(e.getPlayer().getLocation()); + if (!plugin.getIslands().playerIsOnIsland(e.getPlayer())) { + // Not on island + // Minecarts and other storage entities + //plugin.getLogger().info("DEBUG: " + e.getRightClicked().getType().toString()); + //plugin.getLogger().info("DEBUG: " + p.getItemInHand()); + // Handle village trading + if (e.getRightClicked() != null && e.getRightClicked().getType().equals(EntityType.VILLAGER)) { + if (island != null) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: island is not null"); + plugin.getLogger().info("DEBUG: island is not spawn"); + plugin.getLogger().info("DEBUG: villager trading is " + island.getFlag(SettingsFlag.VILLAGER_TRADING)); + } + if ((!island.getFlag(SettingsFlag.VILLAGER_TRADING) && !island.getMembers().contains(p.getUniqueId()))) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + } + // Handle name tags and dyes + if (Util.playerIsHolding(p, Material.NAME_TAG) || Util.playerIsHolding(p, Material.INK_SACK)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + e.getPlayer().updateInventory(); + return; + } + // Handle cookies (to animals) + if (Util.playerIsHolding(p, Material.COOKIE) && e.getRightClicked() instanceof Animals) { + if (island == null && !Settings.defaultWorldSettings.get(SettingsFlag.HURT_ANIMALS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + if (island != null) { + if ((!island.getFlag(SettingsFlag.HURT_ANIMALS) && !island.getMembers().contains(p.getUniqueId()))) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + } + // Handle breeding + if (e.getRightClicked() instanceof Animals) { + for (ItemStack item : Util.getPlayerInHandItems(p)) { + Material type = item.getType(); + if (type == Material.EGG || type == Material.WHEAT || type == Material.CARROT_ITEM || type == Material.SEEDS) { + if (island == null && !Settings.defaultWorldSettings.get(SettingsFlag.BREEDING)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + if (island != null) { + if ((!island.getFlag(SettingsFlag.BREEDING) && !island.getMembers().contains(p.getUniqueId()))) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + } + } + } + } + switch (e.getRightClicked().getType()) { + case CREEPER: + // This seems to be called when the player is in Creative mode... + if (!Settings.allowCreeperGriefing) { + for (ItemStack item : Util.getPlayerInHandItems(e.getPlayer())) { + if (item != null && item.getType().equals(Material.FLINT_AND_STEEL)) { + if (!island.getMembers().contains(e.getPlayer().getUniqueId())) { + // Visitor + litCreeper.add(e.getRightClicked().getUniqueId()); + if (DEBUG) { + plugin.getLogger().info("DEBUG: visitor lit creeper"); + } + } + } + } + } + break; + case LLAMA: + case SKELETON_HORSE: + case ZOMBIE_HORSE: + case HORSE: + //plugin.getLogger().info("Horse riding"); + if (island == null && !Settings.defaultWorldSettings.get(SettingsFlag.MOUNT_RIDING)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + if (island != null && !island.getFlag(SettingsFlag.MOUNT_RIDING)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + break; + case ITEM_FRAME: + // This is to place items in an item frame + if (island == null && !Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + if (island != null) { + if (!island.getFlag(SettingsFlag.PLACE_BLOCKS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + break; + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + //plugin.getLogger().info("Minecarts"); + if (island == null && !Settings.defaultWorldSettings.get(SettingsFlag.OPEN_CHESTS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + if (island != null) { + if (!island.getFlag(SettingsFlag.OPEN_CHESTS)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + break; + default: + break; + } + } + } + + /** + * Prevents fire spread + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockBurn(BlockBurnEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Util.inWorld(e.getBlock())) { + //plugin.getLogger().info("DEBUG: Not in world"); + return; + } + if (actionAllowed(e.getBlock().getLocation(), SettingsFlag.FIRE_SPREAD)) { + return; + } + e.setCancelled(true); + } + + /** + * Prevent fire spread + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlockSpread(BlockSpreadEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info(e.getSource().getType().toString()); + } + if (e.getSource().getType() == Material.FIRE) { + if (!Util.inWorld(e.getBlock())) { + //plugin.getLogger().info("DEBUG: Not in world"); + return; + } + if (actionAllowed(e.getBlock().getLocation(), SettingsFlag.FIRE_SPREAD)) { + return; + } + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockIgnite(final BlockIgniteEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info(e.getCause().name()); + } + if (!Util.inWorld(e.getBlock())) { + //plugin.getLogger().info("DEBUG: Not in world"); + return; + } + // Check if this is a portal lighting + if (e.getBlock() != null && e.getBlock().getType().equals(Material.OBSIDIAN)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: portal lighting"); + return; + } + if (e.getCause() != null) { + if (DEBUG) + plugin.getLogger().info("DEBUG: ignite cause = " + e.getCause()); + switch (e.getCause()) { + case ENDER_CRYSTAL: + case EXPLOSION: + case FIREBALL: + case LIGHTNING: + if (!actionAllowed(e.getBlock().getLocation(), SettingsFlag.FIRE)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: canceling fire"); + e.setCancelled(true); + } + break; + case FLINT_AND_STEEL: + Set transparent = new HashSet(); + transparent.add(Material.AIR); + if (DEBUG) { + plugin.getLogger().info("DEBUG: block = " + e.getBlock()); + //plugin.getLogger().info("DEBUG: target block = " + e.getPlayer().getTargetBlock(transparent, 10)); + } + // Check if this is allowed + if (e.getPlayer() != null && (e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypass"))) { + return; + } + if (!actionAllowed(e.getBlock().getLocation(), SettingsFlag.FIRE)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: canceling fire"); + // If this was not a player, just stop it + if (e.getPlayer() == null) { + e.setCancelled(true); + break; + } + // Get target block + Block targetBlock = e.getPlayer().getTargetBlock(transparent, 10); + if (targetBlock.getType().equals(Material.OBSIDIAN)) { + final MaterialData md = new MaterialData(e.getBlock().getType(), e.getBlock().getData()); + new BukkitRunnable() { + + @Override + public void run() { + if (e.getBlock().getType().equals(Material.FIRE)) { + e.getBlock().setType(md.getItemType()); + e.getBlock().setData(md.getData()); + } + + } + }.runTask(plugin); + } else { + e.setCancelled(true); + } + } + break; + + case LAVA: + case SPREAD: + // Check if this is a portal lighting + if (e.getBlock() != null && e.getBlock().getType().equals(Material.OBSIDIAN)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: obsidian lighting"); + return; + } + if (!actionAllowed(e.getBlock().getLocation(), SettingsFlag.FIRE_SPREAD)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: canceling fire spread"); + e.setCancelled(true); + } + break; + default: + break; + } + } + } + + + /** + * Pressure plates + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlateStep(PlayerInteractEvent e) { + if (DEBUG) { + plugin.getLogger().info("pressure plate = " + e.getEventName()); + plugin.getLogger().info("action = " + e.getAction()); + } + if (!Util.inWorld(e.getPlayer()) || !e.getAction().equals(Action.PHYSICAL) + || e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || plugin.getIslands().playerIsOnIsland(e.getPlayer())) { + //plugin.getLogger().info("DEBUG: Not in world"); + return; + } + // Check island + Island island = plugin.getIslands().getProtectedIslandAt(e.getPlayer().getLocation()); + if ((island == null && Settings.defaultWorldSettings.get(SettingsFlag.PRESSURE_PLATE))) { + return; + } + if (island != null && island.getFlag(SettingsFlag.PRESSURE_PLATE)) { + return; + } + // Block action + UUID playerUUID = e.getPlayer().getUniqueId(); + if (!onPlate.containsKey(playerUUID)) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(playerUUID).get("island.protected")); + Vector v = e.getPlayer().getLocation().toVector(); + onPlate.put(playerUUID, new Vector(v.getBlockX(), v.getBlockY(), v.getBlockZ())); + } + e.setCancelled(true); + return; + } + + /** + * Removes the player from the plate map + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onStepOffPlate(PlayerMoveEvent e) { + if (!onPlate.containsKey(e.getPlayer().getUniqueId())) { + return; + } + Vector v = e.getPlayer().getLocation().toVector(); + if (!(new Vector(v.getBlockX(), v.getBlockY(), v.getBlockZ())).equals(onPlate.get(e.getPlayer().getUniqueId()))) { + onPlate.remove(e.getPlayer().getUniqueId()); + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onPistonExtend(BlockPistonExtendEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + Location pistonLoc = e.getBlock().getLocation(); + if (Settings.allowPistonPush || !Util.inWorld(pistonLoc)) { + //plugin.getLogger().info("DEBUG: Not in world"); + return; + } + Island island = plugin.getIslands().getProtectedIslandAt(pistonLoc); + if (island == null || !island.onIsland(pistonLoc)) { + //plugin.getLogger().info("DEBUG: Not on is island protection zone"); + return; + } + // We need to check where the blocks are going to go, not where they are + for (Block b : e.getBlocks()) { + if (!island.onIsland(b.getRelative(e.getDirection()).getLocation())) { + //plugin.getLogger().info("DEBUG: Block is outside protected area"); + e.setCancelled(true); + return; + } + } + } + + /** + * Handle visitor chicken egg throwing + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEggThrow(PlayerEggThrowEvent e) { + if (DEBUG) { + plugin.getLogger().info("egg throwing = " + e.getEventName()); + } + if (!Util.inWorld(e.getPlayer()) || e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || plugin.getIslands().playerIsOnIsland(e.getPlayer()) || plugin.getIslands().isAtSpawn(e.getPlayer().getLocation())) { + return; + } + // Check island + Island island = plugin.getIslands().getProtectedIslandAt(e.getPlayer().getLocation()); + if (island == null) { + return; + } + if (!island.getFlag(SettingsFlag.THROW_EGGS)) { + e.setHatching(false); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + //e.getPlayer().updateInventory(); + } + + return; + } + + /** + * Prevents trees from growing outside of the protected area. + * + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onTreeGrow(final StructureGrowEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + // Check world + if (!Util.inWorld(e.getLocation())) { + return; + } + // Check if this is on an island + Island island = plugin.getIslands().getIslandAt(e.getLocation()); + if (island == null || island.isSpawn()) { + return; + } + Iterator it = e.getBlocks().iterator(); + while (it.hasNext()) { + BlockState b = it.next(); + if (b.getType() == Material.LOG || b.getType() == Material.LOG_2 + || b.getType() == Material.LEAVES || b.getType() == Material.LEAVES_2) { + if (!island.onIsland(b.getLocation())) { + it.remove(); + } + } + } + } + + /** + * Trap TNT being primed by flaming arrows + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onTNTPrimed(final EntityChangeBlockEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info("DEBUG: block = " + e.getBlock().getType()); + plugin.getLogger().info("DEBUG: entity = " + e.getEntityType()); + plugin.getLogger().info("DEBUG: material changing to " + e.getTo()); + } + if (actionAllowed(e.getEntity().getLocation(), SettingsFlag.FIRE)) { + return; + } + if (e.getBlock() == null) { + return; + } + // Check for TNT + if (!e.getBlock().getType().equals(Material.TNT)) { + //plugin.getLogger().info("DEBUG: not tnt"); + return; + } + // Check world + if (!Util.inWorld(e.getBlock())) { + return; + } + // Check if this is on an island + Island island = plugin.getIslands().getIslandAt(e.getBlock().getLocation()); + if (island == null || island.isSpawn()) { + return; + } + // Stop TNT from being damaged if it is being caused by a visitor with a flaming arrow + if (e.getEntity() instanceof Projectile) { + //plugin.getLogger().info("DEBUG: projectile"); + Projectile projectile = (Projectile) e.getEntity(); + // Find out who fired it + if (projectile.getShooter() instanceof Player) { + //plugin.getLogger().info("DEBUG: player shot arrow. Fire ticks = " + projectile.getFireTicks()); + if (projectile.getFireTicks() > 0) { + //plugin.getLogger().info("DEBUG: arrow on fire"); + Player shooter = (Player)projectile.getShooter(); + if (!plugin.getIslands().locationIsAtHome(shooter, true, e.getBlock().getLocation())) { + //plugin.getLogger().info("DEBUG: shooter is not at home"); + // Only say it once a second + // Debounce event (it can be called twice for the same action) + if (!tntBlocks.contains(e.getBlock().getLocation())) { + Util.sendMessage(shooter, ChatColor.RED + plugin.getLocale(shooter.getUniqueId()).get("island.protected")); + tntBlocks.add(e.getBlock().getLocation()); + plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() { + + @Override + public void run() { + tntBlocks.remove(e.getBlock().getLocation()); + }}, 20L); + } + // Remove the arrow + projectile.remove(); + e.setCancelled(true); + return; + } + } + } + } + } + + /** + * Stop redstone if team members are offline and disableOfflineRedstone is TRUE. + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onBlockRedstone(BlockRedstoneEvent e){ + if(Settings.disableOfflineRedstone) { + // Check world + if (!Util.inWorld(e.getBlock())) { + return; + } + // Check if this is on an island + Island island = plugin.getIslands().getIslandAt(e.getBlock().getLocation()); + if (island == null || island.isSpawn()) { + return; + } + for(UUID member : island.getMembers()){ + if(plugin.getServer().getPlayer(member) != null) return; + } + e.setNewCurrent(0); + } + } + + @EventHandler(priority=EventPriority.LOW) + public void onEvent(BlockPistonExtendEvent event) + { + if (!Settings.allowTNTPushing) { + // Check world + if (!Util.inWorld(event.getBlock())) { + return; + } + + for (Block block: event.getBlocks()) { + if (block.getType() == Material.TNT) { + event.setCancelled(true); + break; + } + } + } + /* JAVA 8 + if (event.getBlocks()..stream().anyMatch(it->it.getType()==Material.TNT)) + event.setCancelled(true); + */ + } + + @EventHandler(priority=EventPriority.LOW) + public void onEvent(BlockPistonRetractEvent event) + { + if (!Settings.allowTNTPushing) { + // Check world + if (!Util.inWorld(event.getBlock())) { + return; + } + for (Block block: event.getBlocks()) { + if (block.getType() == Material.TNT) { + event.setCancelled(true); + break; + } + } + } + /* JAVA 8 + if (event.getBlocks().stream().anyMatch(it->it.getType()==Material.TNT)) + event.setCancelled(true); + */ + } + + /** + * Checks for splash damage. If there is any to any affected entity and it's not allowed, it won't work on any of them. + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onSplashPotionSplash(final PotionSplashEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + plugin.getLogger().info("splash entity = " + e.getEntity()); + plugin.getLogger().info("splash entity type = " + e.getEntityType()); + plugin.getLogger().info("splash affected entities = " + e.getAffectedEntities()); + //plugin.getLogger().info("splash hit entity = " + e.getHitEntity()); + } + if (!Util.inWorld(e.getEntity().getLocation())) { + return; + } + // Try to get the shooter + Projectile projectile = (Projectile) e.getEntity(); + if (DEBUG) + plugin.getLogger().info("splash shooter = " + projectile.getShooter()); + if (projectile.getShooter() != null && projectile.getShooter() instanceof Player) { + Player attacker = (Player)projectile.getShooter(); + // Run through all the affected entities + for (LivingEntity entity: e.getAffectedEntities()) { + if (DEBUG) + plugin.getLogger().info("DEBUG: affected splash entity = " + entity); + // Self damage + if (attacker.equals(entity)) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Self damage from splash potion!"); + continue; + } + Island island = plugin.getIslands().getIslandAt(entity.getLocation()); + boolean inNether = false; + if (entity.getWorld().equals(IslandWorld.getNetherWorld())) { + inNether = true; + } + // Monsters being hurt + if (entity instanceof Monster || entity instanceof Slime || entity instanceof Squid) { + // Normal island check + if (island != null && island.getMembers().contains(attacker)) { + // Members always allowed + continue; + } + if (actionAllowed(attacker, entity.getLocation(), SettingsFlag.HURT_MONSTERS)) { + continue; + } + // Not allowed + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + + // Mobs being hurt + if (entity instanceof Animals || entity instanceof IronGolem || entity instanceof Snowman + || entity instanceof Villager) { + if (island != null && (island.getFlag(SettingsFlag.HURT_ANIMALS) || island.getMembers().contains(attacker))) { + continue; + } + if (DEBUG) + plugin.getLogger().info("DEBUG: Mobs not allowed to be hurt. Blocking"); + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("island.protected")); + e.setCancelled(true); + return; + } + + // Establish whether PVP is allowed or not. + boolean pvp = false; + if ((inNether && island != null && island.getFlag(SettingsFlag.PVP_NETHER) || (!inNether && island != null && island.getFlag(SettingsFlag.PVP_OVERWORLD)))) { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed"); + pvp = true; + } + + // Players being hurt PvP + if (entity instanceof Player) { + if (pvp) { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed"); + continue; + } else { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP not allowed"); + Util.sendMessage(attacker, ChatColor.RED + plugin.getLocale(attacker.getUniqueId()).get("targetInPVPArea")); + e.setCancelled(true); + return; + } + } + } + } + } +} diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_8.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_8.java new file mode 100644 index 000000000..ba975ddca --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_8.java @@ -0,0 +1,213 @@ +package us.tastybento.bskyblock.listeners.protection; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +/** + * @author tastybento + * Provides protection to islands - handles newer events that may not + * exist in older servers + */ +public class IslandGuard1_8 implements Listener { + private final BSkyBlock plugin; + private final static boolean DEBUG = false; + + public IslandGuard1_8(final BSkyBlock plugin) { + this.plugin = plugin; + + } + + + /** + * Checks if action is allowed for player in location for flag + * @param player + * @param location + * @param flag + * @return true if allowed + */ + private boolean actionAllowed(Player player, Location location, SettingsFlag flag) { + // This permission bypasses protection + if (player.isOp() || VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) { + return true; + } + Island island = plugin.getIslands().getProtectedIslandAt(location); + if (island != null && (island.getFlag(flag) || island.getMembers().contains(player.getUniqueId()))){ + return true; + } + if (island == null && Settings.defaultWorldSettings.get(flag)) { + return true; + } + return false; + } + + + /** + * Handle interaction with armor stands V1.8 + * Note - some armor stand protection is done in IslandGuard.java, e.g. against projectiles. + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onPlayerInteract(final PlayerInteractAtEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.8 " + e.getEventName()); + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + if (e.getRightClicked() != null && e.getRightClicked().getType().equals(EntityType.ARMOR_STAND)) { + if (actionAllowed(e.getPlayer(), e.getRightClicked().getLocation(), SettingsFlag.ARMOR_STAND)) { + return; + } + e.setCancelled(true); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + } + } + + /** + * Handle V1.8 blocks that need special treatment + * Tilling of coarse dirt into dirt + * Usually prevented because it could lead to an endless supply of dirt with gravel + * + * @param e + */ + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onPlayerInteract(final PlayerInteractEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.8 " + e.getEventName()); + } + if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) { + return; + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + if (e.getPlayer().isOp()) { + return; + } + // This permission bypasses protection + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "craft.dirt")) { + return; + } + // Prevents tilling of coarse dirt into dirt + ItemStack inHand = e.getPlayer().getItemInHand(); + if (inHand.getType() == Material.WOOD_HOE || inHand.getType() == Material.IRON_HOE || inHand.getType() == Material.GOLD_HOE + || inHand.getType() == Material.DIAMOND_HOE || inHand.getType() == Material.STONE_HOE) { + // plugin.getLogger().info("1.8 " + "DEBUG: hoe in hand"); + Block block = e.getClickedBlock(); + // plugin.getLogger().info("1.8 " + "DEBUG: block is " + block.getType() + + // ":" + block.getData()); + // Check if coarse dirt + if (block.getType() == Material.DIRT && block.getData() == (byte) 1) { + // plugin.getLogger().info("1.8 " + "DEBUG: hitting coarse dirt!"); + e.setCancelled(true); + } + } + } + + // Armor stand events + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true) + void placeArmorStandEvent(PlayerInteractEvent e) { + Player p = e.getPlayer(); + if (DEBUG) { + plugin.getLogger().info("1.8 " + "Armor stand place " + e.getEventName()); + } + if (!Util.inWorld(p)) { + return; + } + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + // You can do anything if you are Op + return; + } + + // Check if they are holding armor stand + for (ItemStack inHand : Util.getPlayerInHandItems(e.getPlayer())) { + if (inHand.getType().equals(Material.ARMOR_STAND)) { + // Check island + Island island = plugin.getIslands().getIslandAt(e.getPlayer().getLocation()); + if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + return; + } + if (island !=null && (island.getMembers().contains(p.getUniqueId()) || island.getFlag(SettingsFlag.PLACE_BLOCKS))) { + //plugin.getLogger().info("1.8 " + "DEBUG: armor stand place check"); + if (Settings.limitedBlocks.containsKey("ARMOR_STAND") && Settings.limitedBlocks.get("ARMOR_STAND") > -1) { + //plugin.getLogger().info("1.8 " + "DEBUG: count armor stands"); + int count = island.getTileEntityCount(Material.ARMOR_STAND,e.getPlayer().getWorld()); + //plugin.getLogger().info("1.8 " + "DEBUG: count is " + count + " limit is " + Settings.limitedBlocks.get("ARMOR_STAND")); + if (Settings.limitedBlocks.get("ARMOR_STAND") <= count) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]", + Util.prettifyText(Material.ARMOR_STAND.toString()))).replace("[number]", String.valueOf(Settings.limitedBlocks.get("ARMOR_STAND")))); + e.setCancelled(true); + return; + } + } + return; + } + // plugin.getLogger().info("1.8 " + "DEBUG: stand place cancelled"); + e.setCancelled(true); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.getPlayer().updateInventory(); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void ArmorStandDestroy(EntityDamageByEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.8 " + "IslandGuard New " + e.getEventName()); + } + if (!(e.getEntity() instanceof LivingEntity)) { + return; + } + if (!Util.inWorld(e.getEntity())) { + return; + } + final LivingEntity livingEntity = (LivingEntity) e.getEntity(); + if (!livingEntity.getType().equals(EntityType.ARMOR_STAND)) { + return; + } + if (e.getDamager() instanceof Player) { + Player p = (Player) e.getDamager(); + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + // Check if on island + if (plugin.getIslands().playerIsOnIsland(p)) { + return; + } + // Check island + Island island = plugin.getIslands().getIslandAt(e.getEntity().getLocation()); + if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) { + return; + } + if (island != null && island.getFlag(SettingsFlag.BREAK_BLOCKS)) { + return; + } + Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_9.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_9.java new file mode 100644 index 000000000..6376ac4b7 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_9.java @@ -0,0 +1,498 @@ +package us.tastybento.bskyblock.listeners.protection; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Animals; +import org.bukkit.entity.EnderCrystal; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Snowman; +import org.bukkit.entity.Squid; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.EntityBlockFormEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.LingeringPotionSplashEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; +import us.tastybento.bskyblock.generators.IslandWorld; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +/** + * @author tastybento + * Provides protection to islands - handles newer events that may not + * exist in older servers + */ +public class IslandGuard1_9 implements Listener { + private final BSkyBlock plugin; + private final static boolean DEBUG = false; + private HashMap thrownPotions; + + public IslandGuard1_9(final BSkyBlock plugin) { + this.plugin = plugin; + this.thrownPotions = new HashMap(); + } + + /** + * Handles Frost Walking on visitor's islands + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onBlockForm(EntityBlockFormEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +e.getEventName()); + } + if (e.getEntity() instanceof Player && e.getNewState().getType().equals(Material.FROSTED_ICE)) { + Player player= (Player) e.getEntity(); + if (!Util.inWorld(player)) { + return; + } + if (player.isOp()) { + return; + } + // This permission bypasses protection + if (VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + // Check island + Island island = plugin.getIslands().getIslandAt(player.getLocation()); + if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + return; + } + if (island !=null) { + if (island.getMembers().contains(player.getUniqueId()) || island.getFlag(SettingsFlag.PLACE_BLOCKS)) { + return; + } + } + // Silently cancel the event + e.setCancelled(true); + } + } + + + /** + * Handle interaction with end crystals 1.9 + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onHitEndCrystal(final PlayerInteractAtEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +e.getEventName()); + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + if (e.getPlayer().isOp()) { + return; + } + // This permission bypasses protection + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + if (e.getRightClicked() != null && e.getRightClicked().getType().equals(EntityType.ENDER_CRYSTAL)) { + // Check island + Island island = plugin.getIslands().getIslandAt(e.getRightClicked().getLocation()); + if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) { + return; + } + if (island !=null) { + if (island.getMembers().contains(e.getPlayer().getUniqueId()) || island.getFlag(SettingsFlag.BREAK_BLOCKS)) { + return; + } + } + e.setCancelled(true); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + } + } + + // End crystal + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true) + void placeEndCrystalEvent(PlayerInteractEvent e) { + Player p = e.getPlayer(); + if (DEBUG) { + plugin.getLogger().info("1.9 " +"End crystal place " + e.getEventName()); + } + if (!Util.inWorld(p)) { + return; + } + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + // You can do anything if you are Op + return; + } + + // Check if they are holding armor stand + for (ItemStack inHand : Util.getPlayerInHandItems(e.getPlayer())) { + if (inHand.getType().equals(Material.END_CRYSTAL)) { + // Check island + Island island = plugin.getIslands().getIslandAt(e.getPlayer().getLocation()); + if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) { + return; + } + if (island !=null && (island.getMembers().contains(p.getUniqueId()) || island.getFlag(SettingsFlag.PLACE_BLOCKS))) { + //plugin.getLogger().info("1.9 " +"DEBUG: armor stand place check"); + if (Settings.limitedBlocks.containsKey("END_CRYSTAL") && Settings.limitedBlocks.get("END_CRYSTAL") > -1) { + //plugin.getLogger().info("1.9 " +"DEBUG: count armor stands"); + int count = island.getTileEntityCount(Material.END_CRYSTAL,e.getPlayer().getWorld()); + //plugin.getLogger().info("1.9 " +"DEBUG: count is " + count + " limit is " + Settings.limitedBlocks.get("ARMOR_STAND")); + if (Settings.limitedBlocks.get("END_CRYSTAL") <= count) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]", + Util.prettifyText(Material.END_CRYSTAL.toString()))).replace("[number]", String.valueOf(Settings.limitedBlocks.get("END_CRYSTAL")))); + e.setCancelled(true); + return; + } + } + return; + } + // plugin.getLogger().info("1.9 " +"DEBUG: stand place cancelled"); + e.setCancelled(true); + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.getPlayer().updateInventory(); + } + } + + } + + /** + * Handle end crystal damage by visitors + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void EndCrystalDamage(EntityDamageByEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +"IslandGuard 1_9 " + e.getEventName()); + plugin.getLogger().info("1.9 " +"Entity is " + e.getEntityType()); + } + if (e.getEntity() == null || !Util.inWorld(e.getEntity())) { + return; + } + if (!(e.getEntity() instanceof EnderCrystal)) { + if (DEBUG) { + plugin.getLogger().info("1.9 Entity is not End crystal it is " + e.getEntityType()); + } + return; + } + if (DEBUG) { + plugin.getLogger().info("1.9 Damager is " + e.getDamager()); + } + Player p = null; + if (e.getDamager() instanceof Player) { + p = (Player) e.getDamager(); + if (DEBUG) { + plugin.getLogger().info("1.9 Damager is a player"); + } + } else if (e.getDamager() instanceof Projectile) { + // Get the shooter + Projectile projectile = (Projectile)e.getDamager(); + ProjectileSource shooter = projectile.getShooter(); + if (shooter instanceof Player) { + p = (Player)shooter; + } + if (DEBUG) { + plugin.getLogger().info("1.9 " +"Damager is a projectile shot by " + p.getName()); + } + } + if (p != null) { + if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +"Bypassing protection"); + } + return; + } + // Check if on island + if (plugin.getIslands().playerIsOnIsland(p)) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +"Player is on their own island"); + } + return; + } + // Check island + Island island = plugin.getIslands().getIslandAt(e.getEntity().getLocation()); + if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) { + return; + } + if (island != null && island.getFlag(SettingsFlag.BREAK_BLOCKS)) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +"Visitor is allowed to break blocks"); + } + return; + } + Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + + } + + /** + * Handles end crystal explosions + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onExplosion(final EntityExplodeEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +e.getEventName()); + plugin.getLogger().info("1.9 " +"Entity exploding is " + e.getEntity()); + } + if (e.getEntity() == null || !e.getEntityType().equals(EntityType.ENDER_CRYSTAL)) { + if (DEBUG) { + plugin.getLogger().info("1.9 " +"Entity is not an END CRYSTAL"); + } + return; + } + + if (!Util.inWorld(e.getLocation())) { + return; + } + // General settings irrespective of whether this is allowed or not + if (!Settings.allowTNTDamage) { + plugin.getLogger().info("1.9 " +"TNT block damage prevented"); + e.blockList().clear(); + } else { + if (!Settings.allowChestDamage) { + List toberemoved = new ArrayList(); + // Save the chest blocks in a list + for (Block b : e.blockList()) { + switch (b.getType()) { + case CHEST: + case ENDER_CHEST: + case STORAGE_MINECART: + case TRAPPED_CHEST: + toberemoved.add(b); + break; + default: + break; + } + } + // Now delete them + for (Block b : toberemoved) { + e.blockList().remove(b); + } + } + } + // prevent at spawn + if (plugin.getIslands().isAtSpawn(e.getLocation())) { + e.blockList().clear(); + e.setCancelled(true); + } + + } + + /** + * Handle blocks that need special treatment + * Tilling of coarse dirt into dirt using off-hand (regular hand is in 1.8) + * Usually prevented because it could lead to an endless supply of dirt with gravel + * + * @param e + */ + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onPlayerInteract(final PlayerInteractEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 " + e.getEventName()); + } + if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) { + return; + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + if (e.getPlayer().isOp()) { + return; + } + // This permission bypasses protection + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "craft.dirt")) { + return; + } + // Prevents tilling of coarse dirt into dirt + ItemStack inHand = e.getPlayer().getInventory().getItemInOffHand(); + if (inHand.getType() == Material.WOOD_HOE || inHand.getType() == Material.IRON_HOE || inHand.getType() == Material.GOLD_HOE + || inHand.getType() == Material.DIAMOND_HOE || inHand.getType() == Material.STONE_HOE) { + // plugin.getLogger().info("1.8 " + "DEBUG: hoe in hand"); + Block block = e.getClickedBlock(); + // plugin.getLogger().info("1.8 " + "DEBUG: block is " + block.getType() + + // ":" + block.getData()); + // Check if coarse dirt + if (block.getType() == Material.DIRT && block.getData() == (byte) 1) { + // plugin.getLogger().info("1.8 " + "DEBUG: hitting coarse dirt!"); + e.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onLingeringPotionSplash(final LingeringPotionSplashEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 " + e.getEventName()); + plugin.getLogger().info("1.9 entity = " + e.getEntity()); + plugin.getLogger().info("1.9 entity type = " + e.getEntityType()); + plugin.getLogger().info("1.9 radius = " + e.getAreaEffectCloud().getRadius()); + plugin.getLogger().info("1.9 id = " + e.getAreaEffectCloud().getEntityId()); + plugin.getLogger().info("1.9 hit entity = " + e.getHitEntity()); + } + if (!Util.inWorld(e.getEntity().getLocation())) { + return; + } + // Try to get the shooter + Projectile projectile = (Projectile) e.getEntity(); + plugin.getLogger().info("shooter = " + projectile.getShooter()); + if (projectile.getShooter() != null && projectile.getShooter() instanceof Player) { + UUID uuid = ((Player)projectile.getShooter()).getUniqueId(); + // Store it and remove it when the effect is gone + thrownPotions.put(e.getAreaEffectCloud().getEntityId(), uuid); + plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() { + + @Override + public void run() { + if (DEBUG) + plugin.getLogger().info("DEBUG: Effect finished"); + thrownPotions.remove(e.getAreaEffectCloud().getEntityId()); + + }}, e.getAreaEffectCloud().getDuration()); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onLingeringPotionDamage(final EntityDamageByEntityEvent e) { + if (DEBUG) { + plugin.getLogger().info("1.9 lingering potion damage " + e.getEventName()); + plugin.getLogger().info("1.9 lingering potion entity = " + e.getEntity()); + plugin.getLogger().info("1.9 lingering potion entity type = " + e.getEntityType()); + plugin.getLogger().info("1.9 lingering potion cause = " + e.getCause()); + plugin.getLogger().info("1.9 lingering potion damager = " + e.getDamager()); + } + if (!Util.inWorld(e.getEntity().getLocation())) { + return; + } + if (e.getEntity() == null || e.getEntity().getUniqueId() == null) { + return; + } + if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && thrownPotions.containsKey(e.getDamager().getEntityId())) { + UUID attacker = thrownPotions.get(e.getDamager().getEntityId()); + // Self damage + if (attacker.equals(e.getEntity().getUniqueId())) { + if (DEBUG) + plugin.getLogger().info("DEBUG: Self damage from lingering potion!"); + return; + } + Island island = plugin.getIslands().getIslandAt(e.getEntity().getLocation()); + boolean inNether = false; + if (e.getEntity().getWorld().equals(IslandWorld.getNetherWorld())) { + inNether = true; + } + // Monsters being hurt + if (e.getEntity() instanceof Monster || e.getEntity() instanceof Slime || e.getEntity() instanceof Squid) { + // Normal island check + if (island != null && island.getMembers().contains(attacker)) { + // Members always allowed + return; + } + if (actionAllowed(attacker, e.getEntity().getLocation(), SettingsFlag.HURT_MONSTERS)) { + return; + } + // Not allowed + e.setCancelled(true); + return; + } + + // Mobs being hurt + if (e.getEntity() instanceof Animals || e.getEntity() instanceof IronGolem || e.getEntity() instanceof Snowman + || e.getEntity() instanceof Villager) { + if (island != null && (island.getFlag(SettingsFlag.HURT_ANIMALS) || island.getMembers().contains(attacker))) { + return; + } + if (DEBUG) + plugin.getLogger().info("DEBUG: Mobs not allowed to be hurt. Blocking"); + e.setCancelled(true); + return; + } + + // Establish whether PVP is allowed or not. + boolean pvp = false; + if ((inNether && island != null && island.getFlag(SettingsFlag.PVP_NETHER) || (!inNether && island != null && island.getFlag(SettingsFlag.PVP_OVERWORLD)))) { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed"); + pvp = true; + } + + // Players being hurt PvP + if (e.getEntity() instanceof Player) { + if (pvp) { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed"); + return; + } else { + if (DEBUG) plugin.getLogger().info("DEBUG: PVP not allowed"); + e.setCancelled(true); + return; + } + } + } + } + + /** + * Checks if action is allowed for player in location for flag + * @param uuid + * @param location + * @param flag + * @return true if allowed + */ + private boolean actionAllowed(UUID uuid, Location location, SettingsFlag flag) { + Player player = plugin.getServer().getPlayer(uuid); + if (player == null) { + return actionAllowed(location, flag); + } + // This permission bypasses protection + if (player.isOp() || VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) { + return true; + } + Island island = plugin.getIslands().getProtectedIslandAt(location); + if (island != null && (island.getFlag(flag) || island.getMembers().contains(player.getUniqueId()))){ + return true; + } + if (island == null && Settings.defaultWorldSettings.get(flag)) { + return true; + } + return false; + } + + /** + * Action allowed in this location + * @param location + * @param flag + * @return true if allowed + */ + private boolean actionAllowed(Location location, SettingsFlag flag) { + Island island = plugin.getIslands().getProtectedIslandAt(location); + if (island != null && island.getFlag(flag)){ + return true; + } + if (island == null && Settings.defaultWorldSettings.get(flag)) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/NetherEvents.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/NetherEvents.java new file mode 100644 index 000000000..ffd96a3ab --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/NetherEvents.java @@ -0,0 +1,232 @@ +package us.tastybento.bskyblock.listeners.protection; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World.Environment; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityPortalEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.util.Vector; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.generators.IslandWorld; +import us.tastybento.bskyblock.util.SafeSpotTeleport; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +public class NetherEvents implements Listener { + private final BSkyBlock plugin; + private final static boolean DEBUG = false; + + public NetherEvents(BSkyBlock plugin) { + this.plugin = plugin; + } + + /** + * This handles non-player portal use + * Currently disables portal use by entities + * + * @param event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityPortal(EntityPortalEvent event) { + if (DEBUG) + plugin.getLogger().info("DEBUG: nether portal entity " + event.getFrom().getBlock().getType()); + // If the nether is disabled then quit immediately + if (!Settings.netherGenerate || IslandWorld.getNetherWorld() == null) { + return; + } + if (event.getEntity() == null) { + return; + } + if (event.getFrom() != null && event.getFrom().getBlock().getType().equals(Material.ENDER_PORTAL)) { + event.setCancelled(true); + // Same action for all worlds except the end itself + if (!event.getFrom().getWorld().getEnvironment().equals(Environment.THE_END)) { + if (plugin.getServer().getWorld(Settings.worldName + "_the_end") != null) { + // The end exists + Location end_place = plugin.getServer().getWorld(Settings.worldName + "_the_end").getSpawnLocation(); + event.getEntity().teleport(end_place); + if (DEBUG) + plugin.getLogger().info("DEBUG: Result teleported " + event.getEntityType() + " to " + end_place); + return; + } + } + return; + } + Location currentLocation = event.getFrom().clone(); + String currentWorld = currentLocation.getWorld().getName(); + // Only operate if this is Island territory + if (!currentWorld.equalsIgnoreCase(Settings.worldName) && !currentWorld.equalsIgnoreCase(Settings.worldName + "_nether")) { + return; + } + // No entities may pass with the old nether + if (!Settings.netherIslands) { + event.setCancelled(true); + return; + } + // New nether + // Entities can pass only if there are adjoining portals + Location dest = event.getFrom().toVector().toLocation(IslandWorld.getIslandWorld()); + if (event.getFrom().getWorld().getEnvironment().equals(Environment.NORMAL)) { + dest = event.getFrom().toVector().toLocation(IslandWorld.getNetherWorld()); + } + // Vehicles + if (event.getEntity() instanceof Vehicle) { + Vehicle vehicle = (Vehicle)event.getEntity(); + vehicle.eject(); + } + new SafeSpotTeleport(plugin, event.getEntity(), dest); + event.setCancelled(true); + } + + // Nether portal spawn protection + + /** + * Function to check proximity to nether spawn location + * + * @param player + * @return true if in the spawn area, false if not + */ + private boolean awayFromSpawn(Player player) { + Vector p = player.getLocation().toVector().multiply(new Vector(1, 0, 1)); + Vector spawn = player.getWorld().getSpawnLocation().toVector().multiply(new Vector(1, 0, 1)); + if (spawn.distanceSquared(p) < (Settings.netherSpawnRadius * Settings.netherSpawnRadius)) { + return false; + } else { + return true; + } + } + + /** + * Prevents blocks from being broken + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onBlockBreak(final BlockBreakEvent e) { + if (DEBUG) + plugin.getLogger().info("DEBUG: " + e.getEventName()); + // plugin.getLogger().info("Block break"); + if ((e.getPlayer().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_nether") && !Settings.netherIslands) + || e.getPlayer().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_the_end")) { + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + if (DEBUG) + plugin.getLogger().info("Block break in island nether"); + if (!awayFromSpawn(e.getPlayer()) && !e.getPlayer().isOp()) { + Util.sendMessage(e.getPlayer(), plugin.getLocale(e.getPlayer().getUniqueId()).get("nether.spawnisprotected")); + e.setCancelled(true); + } + } + + } + + /** + * Prevents placing of blocks + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onPlayerBlockPlace(final BlockPlaceEvent e) { + if (DEBUG) + plugin.getLogger().info("DEBUG: " + e.getEventName()); + if (!Settings.netherIslands) { + if (e.getPlayer().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_nether") + || e.getPlayer().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_the_end")) { + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + if (!awayFromSpawn(e.getPlayer()) && !e.getPlayer().isOp()) { + e.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onBucketEmpty(final PlayerBucketEmptyEvent e) { + if (DEBUG) + plugin.getLogger().info("DEBUG: " + e.getEventName()); + if (!Settings.netherIslands) { + if (e.getPlayer().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_nether") + || e.getPlayer().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_the_end")) { + if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) { + return; + } + if (!awayFromSpawn(e.getPlayer()) && !e.getPlayer().isOp()) { + e.setCancelled(true); + } + } + } + } + + /** + * Prevent the Nether spawn from being blown up + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onExplosion(final EntityExplodeEvent e) { + if (Settings.netherIslands) { + // Not used in the new nether + return; + } + // Find out what is exploding + Entity expl = e.getEntity(); + if (expl == null) { + return; + } + // Check world + if (!e.getEntity().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_nether") + || e.getEntity().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_the_end")) { + return; + } + Location spawn = e.getLocation().getWorld().getSpawnLocation(); + Location loc = e.getLocation(); + if (spawn.distance(loc) < Settings.netherSpawnRadius) { + e.blockList().clear(); + } + } + + /** + * Converts trees to gravel and glowstone + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onTreeGrow(final StructureGrowEvent e) { + if (DEBUG) + plugin.getLogger().info("DEBUG: " + e.getEventName()); + + if (!Settings.netherTrees) { + return; + } + if (!Settings.netherGenerate || IslandWorld.getNetherWorld() == null) { + return; + } + // Check world + if (!e.getLocation().getWorld().equals(IslandWorld.getNetherWorld())) { + return; + } + for (BlockState b : e.getBlocks()) { + if (b.getType() == Material.LOG || b.getType() == Material.LOG_2) { + b.setType(Material.GRAVEL); + } else if (b.getType() == Material.LEAVES || b.getType() == Material.LEAVES_2) { + b.setType(Material.GLOWSTONE); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/listeners/protection/VisitorGuard.java b/src/main/java/us/tastybento/bskyblock/listeners/protection/VisitorGuard.java new file mode 100644 index 000000000..284f8f95b --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/protection/VisitorGuard.java @@ -0,0 +1,189 @@ +package us.tastybento.bskyblock.listeners.protection; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerRespawnEvent; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.database.objects.Island.SettingsFlag; +import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.VaultHelper; + +/** + * @author tastybento + * Provides protection to islands + */ +public class VisitorGuard implements Listener { + private final BSkyBlock plugin; + private static final boolean DEBUG = false; + + public VisitorGuard(final BSkyBlock plugin) { + this.plugin = plugin; + } + + /* + * Prevent dropping items if player dies on another island + * This option helps reduce the down side of dying due to traps, etc. + * Also handles muting of death messages + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onVistorDeath(final PlayerDeathEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Util.inWorld(e.getEntity())) { + return; + } + // Mute death messages + if (Settings.muteDeathMessages) { + e.setDeathMessage(null); + } + // If visitors will keep items and their level on death + // This will override any global settings + if (Settings.allowVisitorKeepInvOnDeath) { + // If the player is not a visitor then they die and lose everything - + // sorry :-( + Island island = plugin.getIslands().getProtectedIslandAt(e.getEntity().getLocation()); + if (island != null && !island.getMembers().contains(e.getEntity().getUniqueId())) { + // They are a visitor + InventorySave.getInstance().savePlayerInventory(e.getEntity()); + e.getDrops().clear(); + e.setKeepLevel(true); + e.setDroppedExp(0); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onVistorSpawn(final PlayerRespawnEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + // This will override any global settings + if (Settings.allowVisitorKeepInvOnDeath) { + InventorySave.getInstance().loadPlayerInventory(e.getPlayer()); + InventorySave.getInstance().clearSavedInventory(e.getPlayer()); + } + } + /* + * Prevent item pickup by visitors + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onVisitorPickup(final PlayerPickupItemEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + Island island = plugin.getIslands().getIslandAt(e.getItem().getLocation()); + if ((island != null && island.getFlag(SettingsFlag.ITEM_PICKUP)) + || e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || plugin.getIslands().locationIsOnIsland(e.getPlayer(), e.getItem().getLocation())) { + return; + } + e.setCancelled(true); + } + + /* + * Prevent item drop by visitors + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onVisitorDrop(final PlayerDropItemEvent e) { + if (DEBUG) { + plugin.getLogger().info(e.getEventName()); + } + if (!Util.inWorld(e.getPlayer())) { + return; + } + Island island = plugin.getIslands().getIslandAt(e.getItemDrop().getLocation()); + if ((island != null && island.getFlag(SettingsFlag.ITEM_DROP)) + || e.getPlayer().isOp() || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || plugin.getIslands().locationIsOnIsland(e.getPlayer(), e.getItemDrop().getLocation())) { + return; + } + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + + /** + * Prevents visitors from using commands on islands, like /spawner + * @param e + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onVisitorCommand(final PlayerCommandPreprocessEvent e) { + if (DEBUG) { + plugin.getLogger().info("Visitor command " + e.getEventName() + ": " + e.getMessage()); + } + if (!Util.inWorld(e.getPlayer()) || e.getPlayer().isOp() + || VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect") + || plugin.getIslands().locationIsOnIsland(e.getPlayer(), e.getPlayer().getLocation())) { + //plugin.getLogger().info("player is not in world or op etc."); + return; + } + // Check banned commands + //plugin.getLogger().info(Settings.visitorCommandBlockList.toString()); + String[] args = e.getMessage().substring(1).toLowerCase().split(" "); + if (Settings.visitorBannedCommands.contains(args[0])) { + Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected")); + e.setCancelled(true); + } + } + + /** + * Prevents visitors from getting damage if invinciblevisitors option is set to TRUE + * @param e + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onVisitorGetDamage(EntityDamageEvent e){ + if(!Settings.invincibleVisitor) return; + if(!(e.getEntity() instanceof Player)) return; + + Player p = (Player) e.getEntity(); + if (!Util.inWorld(p) || plugin.getIslands().locationIsOnIsland(p, p.getLocation())) return; + + if (Settings.invincibleVisitorOptions.contains(e.getCause())) e.setCancelled(true); + + else if(e.getCause().equals(DamageCause.VOID)) { + if(plugin.getPlayers().hasIsland(p.getUniqueId())) { + Location safePlace = plugin.getIslands().getSafeHomeLocation(p.getUniqueId(), 1); + if (safePlace != null) { + p.teleport(safePlace); + // Set their fall distance to zero otherwise they crash onto their island and die + p.setFallDistance(0); + e.setCancelled(true); + return; + } + } + // No island, or no safe spot on island + if (plugin.getIslands().getSpawn() != null) { + p.teleport(plugin.getIslands().getSpawnPoint()); + // Set their fall distance to zero otherwise they crash onto their island and die + p.setFallDistance(0); + e.setCancelled(true); + return; + } + // No island spawn, try regular spawn + if (!p.performCommand("spawn")) { + // If this command doesn't work, let them die otherwise they may get trapped in the void forever + return; + } + // Set their fall distance to zero otherwise they crash onto their island and die + p.setFallDistance(0); + e.setCancelled(true); + } + } + +} diff --git a/src/main/java/us/tastybento/bskyblock/schematics/BannerBlock.java b/src/main/java/us/tastybento/bskyblock/schematics/BannerBlock.java index 067227b8b..e385a430a 100644 --- a/src/main/java/us/tastybento/bskyblock/schematics/BannerBlock.java +++ b/src/main/java/us/tastybento/bskyblock/schematics/BannerBlock.java @@ -1,20 +1,3 @@ -/******************************************************************************* - * This file is part of ASkyBlock. - * - * ASkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ASkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ASkyBlock. If not, see . - *******************************************************************************/ - package us.tastybento.bskyblock.schematics; import java.util.ArrayList; diff --git a/src/main/java/us/tastybento/bskyblock/schematics/EntityObject.java b/src/main/java/us/tastybento/bskyblock/schematics/EntityObject.java index 88262f3f8..191bfa230 100644 --- a/src/main/java/us/tastybento/bskyblock/schematics/EntityObject.java +++ b/src/main/java/us/tastybento/bskyblock/schematics/EntityObject.java @@ -1,20 +1,3 @@ -/******************************************************************************* - * This file is part of ASkyBlock. - * - * ASkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ASkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ASkyBlock. If not, see . - *******************************************************************************/ - package us.tastybento.bskyblock.schematics; import org.bukkit.entity.EntityType; diff --git a/src/main/java/us/tastybento/bskyblock/schematics/IslandBlock.java b/src/main/java/us/tastybento/bskyblock/schematics/IslandBlock.java index 5f0de58cc..76692f265 100644 --- a/src/main/java/us/tastybento/bskyblock/schematics/IslandBlock.java +++ b/src/main/java/us/tastybento/bskyblock/schematics/IslandBlock.java @@ -1,20 +1,3 @@ -/******************************************************************************* - * This file is part of ASkyBlock. - * - * ASkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ASkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ASkyBlock. If not, see . - *******************************************************************************/ - package us.tastybento.bskyblock.schematics; import java.util.ArrayList; @@ -59,8 +42,6 @@ public class IslandBlock { private int z; private List signText; private BannerBlock banner; - private SkullBlock skull; - private PotBlock pot; private EntityType spawnerBlockType; // Chest contents private HashMap chestContents = new HashMap(); @@ -219,8 +200,6 @@ public class IslandBlock { this.z = z; signText = null; banner = null; - skull = null; - pot = null; spawnerBlockType = null; chestContents = new HashMap(); } @@ -279,19 +258,6 @@ public class IslandBlock { banner = new BannerBlock(); banner.prep(map); } - /** - * Sets this block up with all the skull data required - * @param map - * @param dataValue - */ - public void setSkull(Map map, int dataValue) { - skull = new SkullBlock(); - skull.prep(map, dataValue); - } - public void setFlowerPot(Map map){ - pot = new PotBlock(); - pot.prep(map); - } /** * Sets the spawner type if this block is a spawner @@ -559,10 +525,6 @@ public class IslandBlock { sign.update(); } else if (banner != null) { banner.set(block); - } else if (skull != null){ - skull.set(block); - } else if (pot != null){ - pot.set(nms, block); } else if (spawnerBlockType != null) { if (block.getTypeId() != typeId) { block.setTypeId(typeId); diff --git a/src/main/java/us/tastybento/bskyblock/schematics/PotBlock.java b/src/main/java/us/tastybento/bskyblock/schematics/PotBlock.java deleted file mode 100644 index 66569c3c3..000000000 --- a/src/main/java/us/tastybento/bskyblock/schematics/PotBlock.java +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************* - * This file is part of ASkyBlock. - * - * ASkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ASkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ASkyBlock. If not, see . - *******************************************************************************/ - -package us.tastybento.bskyblock.schematics; - -import java.util.HashMap; -import java.util.Map; - -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.inventory.ItemStack; - -import us.tastybento.bskyblock.util.nms.NMSAbstraction; -import us.tastybento.org.jnbt.IntTag; -import us.tastybento.org.jnbt.StringTag; -import us.tastybento.org.jnbt.Tag; - -/** - * This class describes pots and is used in schematic importing - * - * @author SpyL1nk - * - */ -public class PotBlock { - private Material potItem; - private int potItemData; - - private static HashMap potItemList; - - static { - potItemList = new HashMap(); - potItemList.put("", Material.AIR); - potItemList.put("minecraft:red_flower", Material.RED_ROSE); - potItemList.put("minecraft:yellow_flower", Material.YELLOW_FLOWER); - potItemList.put("minecraft:sapling", Material.SAPLING); - potItemList.put("minecraft:red_mushroom", Material.RED_MUSHROOM); - potItemList.put("minecraft:brown_mushroom", Material.BROWN_MUSHROOM); - potItemList.put("minecraft:cactus", Material.CACTUS); - potItemList.put("minecraft:deadbush", Material.LONG_GRASS); - potItemList.put("minecraft:tallgrass", Material.LONG_GRASS); - } - - public boolean set(NMSAbstraction nms, Block block) { - if(potItem != Material.AIR){ - nms.setFlowerPotBlock(block, new ItemStack(potItem, 1,(short) potItemData)); - } - return true; - } - - public boolean prep(Map tileData) { - // Initialize as default - potItem = Material.AIR; - potItemData = 0; - try { - if(tileData.containsKey("Item")){ - - // Get the item in the pot - if (tileData.get("Item") instanceof IntTag) { - // Item is a number, not a material - int id = ((IntTag) tileData.get("Item")).getValue(); - potItem = Material.getMaterial(id); - // Check it's a viable pot item - if (!potItemList.containsValue(potItem)) { - // No, so reset to AIR - potItem = Material.AIR; - } - } else if (tileData.get("Item") instanceof StringTag) { - // Item is a material - String itemName = ((StringTag) tileData.get("Item")).getValue(); - if (potItemList.containsKey(itemName)){ - // Check it's a viable pot item - if (potItemList.containsKey(itemName)) { - potItem = potItemList.get(itemName); - } - } - } - - if(tileData.containsKey("Data")){ - int dataTag = ((IntTag) tileData.get("Data")).getValue(); - // We should check data for each type of potItem - if(potItem == Material.RED_ROSE){ - if(dataTag >= 0 && dataTag <= 8){ - potItemData = dataTag; - } else { - // Prevent hacks - potItemData = 0; - } - } else if(potItem == Material.YELLOW_FLOWER || - potItem == Material.RED_MUSHROOM || - potItem == Material.BROWN_MUSHROOM || - potItem == Material.CACTUS){ - // Set to 0 anyway - potItemData = 0; - } else if(potItem == Material.SAPLING){ - if(dataTag >= 0 && dataTag <= 4){ - potItemData = dataTag; - } else { - // Prevent hacks - potItemData = 0; - } - } else if(potItem == Material.LONG_GRASS){ - // Only 0 or 2 - if(dataTag == 0 || dataTag == 2){ - potItemData = dataTag; - } else { - potItemData = 0; - } - } else { - // ERROR ? - potItemData = 0; - } - } - else { - potItemData = 0; - } - } - //Bukkit.getLogger().info("Debug: flowerpot item = " + potItem.toString()); - //Bukkit.getLogger().info("Debug: flowerpot item data = " + potItemData); - //Bukkit.getLogger().info("Debug: flowerpot materialdata = " + new MaterialData(potItem,(byte) potItemData).toString()); - } catch (Exception e) { - e.printStackTrace(); - } - return true; - } -} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/schematics/Schematic.java b/src/main/java/us/tastybento/bskyblock/schematics/Schematic.java index 2e5f63c94..0b6c53bb3 100644 --- a/src/main/java/us/tastybento/bskyblock/schematics/Schematic.java +++ b/src/main/java/us/tastybento/bskyblock/schematics/Schematic.java @@ -1,19 +1,3 @@ -/******************************************************************************* - * This file is part of BSkyBlock. - * - * BSkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BSkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with BSkyBlock. If not, see . - *******************************************************************************/ package us.tastybento.bskyblock.schematics; import java.io.File; @@ -988,16 +972,16 @@ public class Schematic { Sign sign = (Sign) signState; if (sign.getLine(0).isEmpty()) { // TODO Add sign - //sign.setLine(0, plugin.myLocale(player.getUniqueId()).signLine1.replace("[player]", player.getName())); + sign.setLine(0, plugin.getLocale(player.getUniqueId()).get("sign.line1").replace("[player]", player.getName())); } if (sign.getLine(1).isEmpty()) { - //sign.setLine(1, plugin.myLocale(player.getUniqueId()).signLine2.replace("[player]", player.getName())); + sign.setLine(1, plugin.getLocale(player.getUniqueId()).get("sign.line2").replace("[player]", player.getName())); } if (sign.getLine(2).isEmpty()) { - //sign.setLine(2, plugin.myLocale(player.getUniqueId()).signLine3.replace("[player]", player.getName())); + sign.setLine(2, plugin.getLocale(player.getUniqueId()).get("sign.line3").replace("[player]", player.getName())); } if (sign.getLine(3).isEmpty()) { - //sign.setLine(3, plugin.myLocale(player.getUniqueId()).signLine4.replace("[player]", player.getName())); + sign.setLine(3, plugin.getLocale(player.getUniqueId()).get("sign.line4").replace("[player]", player.getName())); } // BlockFace direction = ((org.bukkit.material.Sign) // sign.getData()).getFacing(); @@ -1181,12 +1165,6 @@ public class Schematic { if (block.getTypeId() == Material.STANDING_BANNER.getId()) { block.setBanner(tileEntitiesMap.get(new BlockVector(x, y, z))); } - else if (block.getTypeId() == Material.SKULL.getId()) { - block.setSkull(tileEntitiesMap.get(new BlockVector(x, y, z)), block.getData()); - } - else if (block.getTypeId() == Material.FLOWER_POT.getId()) { - block.setFlowerPot(tileEntitiesMap.get(new BlockVector(x, y, z))); - } } // Monster spawner blocks if (block.getTypeId() == Material.MOB_SPAWNER.getId()) { diff --git a/src/main/java/us/tastybento/bskyblock/schematics/SchematicsMgr.java b/src/main/java/us/tastybento/bskyblock/schematics/SchematicsMgr.java index 2c811264b..29a0cf66d 100644 --- a/src/main/java/us/tastybento/bskyblock/schematics/SchematicsMgr.java +++ b/src/main/java/us/tastybento/bskyblock/schematics/SchematicsMgr.java @@ -164,7 +164,7 @@ public class SchematicsMgr { if (schematic.isVisible()) { // Check if it's a nether island, but the nether is not enables if (schematic.getBiome().equals(Biome.HELL)) { - if (Settings.createNether && IslandWorld.getNetherWorld() != null) { + if (Settings.netherGenerate && IslandWorld.getNetherWorld() != null) { result.add(schematic); } } else { diff --git a/src/main/java/us/tastybento/bskyblock/schematics/SkullBlock.java b/src/main/java/us/tastybento/bskyblock/schematics/SkullBlock.java deleted file mode 100644 index b46e83564..000000000 --- a/src/main/java/us/tastybento/bskyblock/schematics/SkullBlock.java +++ /dev/null @@ -1,308 +0,0 @@ -/******************************************************************************* - * This file is part of ASkyBlock. - * - * ASkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ASkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ASkyBlock. If not, see . - *******************************************************************************/ - -package us.tastybento.bskyblock.schematics; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.UUID; - -import org.bukkit.Material; -import org.bukkit.SkullType; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.Skull; - -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; - -import us.tastybento.org.jnbt.ByteTag; -import us.tastybento.org.jnbt.CompoundTag; -import us.tastybento.org.jnbt.IntTag; -import us.tastybento.org.jnbt.ListTag; -import us.tastybento.org.jnbt.StringTag; -import us.tastybento.org.jnbt.Tag; - -/** - * This class describes skulls and is used in schematic importing - * - * @author SpyL1nk - * - */ -public class SkullBlock { - - private static final Random random = new Random(); - private static final String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - private SkullType skullType; - private String skullOwnerName; - private String skullOwnerUUID; - private BlockFace skullRotation; - private int skullStanding; - private String skullTextureValue = null; - private String skullTextureSignature = null; - - private static HashMap skullTypeList; - private static HashMap skullRotationList; - - static { - skullTypeList = new HashMap(); - skullTypeList.put(0, SkullType.SKELETON); - skullTypeList.put(1, SkullType.WITHER); - skullTypeList.put(2, SkullType.ZOMBIE); - skullTypeList.put(3, SkullType.PLAYER); - skullTypeList.put(4, SkullType.CREEPER); - } - - static { - skullRotationList = new HashMap(); - skullRotationList.put(0, BlockFace.NORTH); - skullRotationList.put(1, BlockFace.NORTH_NORTH_EAST); - skullRotationList.put(2, BlockFace.NORTH_EAST); - skullRotationList.put(3, BlockFace.EAST_NORTH_EAST); - skullRotationList.put(4, BlockFace.EAST); - skullRotationList.put(5, BlockFace.EAST_SOUTH_EAST); - skullRotationList.put(6, BlockFace.SOUTH_EAST); - skullRotationList.put(7, BlockFace.SOUTH_SOUTH_EAST); - skullRotationList.put(8, BlockFace.SOUTH); - skullRotationList.put(9, BlockFace.SOUTH_SOUTH_WEST); - skullRotationList.put(10, BlockFace.SOUTH_WEST); - skullRotationList.put(11, BlockFace.WEST_SOUTH_WEST); - skullRotationList.put(12, BlockFace.WEST); - skullRotationList.put(13, BlockFace.WEST_NORTH_WEST); - skullRotationList.put(14, BlockFace.NORTH_WEST); - skullRotationList.put(15, BlockFace.NORTH_NORTH_WEST); - } - - @SuppressWarnings("deprecation") - public boolean set(Block block) { - Skull skull = (Skull) block.getState(); - if(skullOwnerName != null){ - skull.setOwner(skullOwnerName); - } - skull.setSkullType(skullType); - skull.setRotation(skullRotation); - skull.setRawData((byte) skullStanding); - // Texture update - if(skullTextureValue != null){ - setSkullWithNonPlayerProfile(skullTextureValue, skullTextureSignature, skullOwnerUUID, skullOwnerName, skull); - } - skull.update(); - return true; - } - - public boolean prep(Map tileData, int dataValue) { - - try { - // Take skull type - if(tileData.containsKey("SkullType")){ - int skullTypeId = (int) ((ByteTag) tileData.get("SkullType")).getValue(); - //Bukkit.getLogger().info("DEBUG: skull type = " + skullTypeId); - if(skullTypeList.containsKey(skullTypeId)){ - skullType = skullTypeList.get(skullTypeId); - } - else { - // Prevent hacks, set to default skull type - skullType = skullTypeList.get(0); - } - } - else{ - // Prevent hacks, set to defaut skull type - skullType = skullTypeList.get(0); - } - - //Bukkit.getLogger().info("DEBUG: skull's data value = " + dataValue); - // Data value 0 is actually unused for skulls, set to 2 to prevent hacks - if(dataValue > 0 && dataValue < 6){ - - skullStanding = dataValue; - - if(tileData.containsKey("Rot")){ - int skullRotId = (int) ((ByteTag) tileData.get("Rot")).getValue(); - //Bukkit.getLogger().info("DEBUG: skull's rotation byte = " + skullRotId); - // Useful for skulls on the floor to insert rotation data - if(skullRotationList.containsKey(skullStanding)){ - skullRotation = skullRotationList.get(skullRotId); - } - else{ - // Prevents hacks - skullRotation = skullRotationList.get(0); - } - } - else{ - skullRotation = skullRotationList.get(0); - } - } - else{ - - skullStanding = 2; - - if(tileData.containsKey("Rot")){ - int skullRotId = ((IntTag) tileData.get("Rot")).getValue(); - //Bukkit.getLogger().info("DEBUG: skull's rotation byte = " + skullRotId); - // Useful for skulls on the floor to insert rotation data - if(skullRotationList.containsKey(skullStanding)){ - skullRotation = skullRotationList.get(skullRotId); - } - // Prevents hacks - else{ - skullRotation = skullRotationList.get(0); - } - } - else{ - skullRotation = skullRotationList.get(0); - } - } - - // Check for Player Heads (skin, texture etc.) - if(skullType == SkullType.PLAYER && tileData.containsKey("Owner")){ - - Map skullOwner = ((CompoundTag) tileData.get("Owner")).getValue(); - - if(skullOwner.containsKey("Name")){ - skullOwnerName = ((StringTag) skullOwner.get("Name")).getValue(); - - //Bukkit.getLogger().info("DEBUG: skull owner's name = " + skullOwnerName); - } - - if(skullOwner.containsKey("Id")){ - skullOwnerUUID = ((StringTag) skullOwner.get("Id")).getValue(); - - //Bukkit.getLogger().info("DEBUG: skull owner's UUID = " + skullOwnerUUID); - } - - if(skullOwner.containsKey("Properties")){ - Map skullOwnerProperties = ((CompoundTag) skullOwner.get("Properties")).getValue(); - - if(skullOwnerProperties.containsKey("textures")){ - - ListTag listTagTextures = (ListTag) skullOwnerProperties.get("textures"); - - //Bukkit.getLogger().info("DEBUG: skull texture's list = " + listTagTextures); - - if(listTagTextures != null){ - - // Logicaly, textures should have only one entry ... - Map skullOwnerTextures = ((CompoundTag) listTagTextures.getValue().get(0)).getValue(); - - if(skullOwnerTextures.containsKey("Value")){ - skullTextureValue = ((StringTag) skullOwnerTextures.get("Value")).getValue(); - - //Bukkit.getLogger().info("DEBUG: skull texture's value = " + skullTextureValue); - } - if(skullOwnerTextures.containsKey("Signature")){ - skullTextureSignature = ((StringTag) skullOwnerTextures.get("Signature")).getValue(); - - //Bukkit.getLogger().info("DEBUG: skull's texture signature = " + skullTextureSignature); - } - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return true; - } - - // Credits: GermanCoding - @SuppressWarnings("deprecation") - public static void setSkullWithNonPlayerProfile(String textureValue, String textureSignature, String ownerUUID, String ownerName, Skull skull) { - if (skull.getType() != Material.SKULL) - throw new IllegalArgumentException("Block must be a skull."); - - skull.getWorld().refreshChunk(skull.getChunk().getX(), skull.getChunk().getZ()); - - - // Difference beetween NonPlayerSkin and PlayerSkin - if(textureSignature != null){ - try { - setSkullProfile(skull, getPlayerProfile(textureValue, textureSignature, ownerUUID, ownerName)); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } - else { - try { - setSkullProfile(skull, getNonPlayerProfile(textureValue, ownerUUID, ownerName)); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } - } - - //skull.getWorld().refreshChunk(skull.getChunk().getX(), skull.getChunk().getZ()); - } - - // Credits: val59000 (THANK YOU VERY MUCH VAL59000 !) - private static void setSkullProfile(Skull skull, GameProfile gameProfile) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - - Field profileField = null; - try { - profileField = skull.getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - profileField.set(skull, gameProfile); - } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); - } - } - - // Credits: dori99xd - public static GameProfile getNonPlayerProfile(String textureValue, String ownerUUID, String ownerName) { - // Create a new GameProfile with .schematic informations or with fake informations - GameProfile newSkinProfile = new GameProfile(ownerUUID == null ? UUID.randomUUID() : UUID.fromString(ownerUUID), - ownerName == null ? getRandomString(16) : null); - - // Insert textures properties - newSkinProfile.getProperties().put("textures", new Property("textures", textureValue)); - return newSkinProfile; - } - - // Credits: dori99xd - public static GameProfile getPlayerProfile(String textureValue, String textureSignature, String ownerUUID, String ownerName) { - // Create a new GameProfile with .schematic informations or with fake informations - GameProfile newSkinProfile = new GameProfile( ownerUUID == null ? UUID.randomUUID() : UUID.fromString(ownerUUID), - ownerName == null ? getRandomString(16) : null); - - // Insert textures properties - newSkinProfile.getProperties().put("textures", new Property("textures", textureValue, textureSignature)); - return newSkinProfile; - } - - // Credits: dori99xd - public static String getRandomString(int length) { - StringBuilder b = new StringBuilder(length); - for(int j = 0; j < length; j++){ - b.append(chars.charAt(random.nextInt(chars.length()))); - } - return b.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/util/DeleteIslandBlocks.java b/src/main/java/us/tastybento/bskyblock/util/DeleteIslandBlocks.java index 794a4b93b..778ed1235 100644 --- a/src/main/java/us/tastybento/bskyblock/util/DeleteIslandBlocks.java +++ b/src/main/java/us/tastybento/bskyblock/util/DeleteIslandBlocks.java @@ -1,19 +1,3 @@ -/******************************************************************************* - * This file is part of BSkyBlock. - * - * BSkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BSkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with BSkyBlock. If not, see . - *******************************************************************************/ package us.tastybento.bskyblock.util; import java.util.HashSet; @@ -115,7 +99,7 @@ public class DeleteIslandBlocks { } if (regen) { world.regenerateChunk(x, z); - if (Settings.islandNether && Settings.createNether) { + if (Settings.netherIslands && Settings.netherGenerate) { if (world.equals(IslandWorld.getIslandWorld())) { IslandWorld.getNetherWorld().regenerateChunk(x, z); } @@ -195,7 +179,7 @@ public class DeleteIslandBlocks { break; } // Nether, if it exists - if (Settings.islandNether && Settings.createNether && y < IslandWorld.getNetherWorld().getMaxHeight() - 8) { + if (Settings.netherIslands && Settings.netherGenerate && y < IslandWorld.getNetherWorld().getMaxHeight() - 8) { b = IslandWorld.getNetherWorld().getBlockAt(xCoord, y, zCoord); bt = b.getType(); if (!b.equals(Material.AIR)) { diff --git a/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java b/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java index d895745c9..456feed70 100644 --- a/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java +++ b/src/main/java/us/tastybento/bskyblock/util/SafeSpotTeleport.java @@ -1,20 +1,3 @@ -/******************************************************************************* - * This file is part of BSkyBlock. - * - * BSkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BSkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with BSkyBlock. If not, see . - *******************************************************************************/ - package us.tastybento.bskyblock.util; import java.util.ArrayList; diff --git a/src/main/java/us/tastybento/bskyblock/util/Util.java b/src/main/java/us/tastybento/bskyblock/util/Util.java index e7877f9cd..0bca00eac 100755 --- a/src/main/java/us/tastybento/bskyblock/util/Util.java +++ b/src/main/java/us/tastybento/bskyblock/util/Util.java @@ -11,10 +11,17 @@ import java.util.List; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.block.Block; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.config.Settings; +import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.util.nms.NMSAbstraction; import us.tastybento.bskyblock.util.placeholders.PlaceholderHandler; @@ -147,4 +154,137 @@ public class Util { // TODO Auto-generated method stub return false; } + + /** + * Results a list of items in a player's hands. Works for older versions of servers + * @param player + * @return list of itemstacks + */ + @SuppressWarnings("deprecation") + public static List getPlayerInHandItems(Player player) { + List result = new ArrayList(2); + if (plugin.getServer().getVersion().contains("(MC: 1.7") + || plugin.getServer().getVersion().contains("(MC: 1.8")) { + if (player.getItemInHand() != null) + result.add(player.getItemInHand()); + return result; + } + if (player.getInventory().getItemInMainHand() != null) + result.add(player.getInventory().getItemInMainHand()); + if (player.getInventory().getItemInOffHand() != null) + result.add(player.getInventory().getItemInOffHand()); + return result; + } + + /** + * Converts a name like IRON_INGOT into Iron Ingot to improve readability + * + * @param ugly + * The string such as IRON_INGOT + * @return A nicer version, such as Iron Ingot + * + * Credits to mikenon on GitHub! + */ + public static String prettifyText(String ugly) { + if (!ugly.contains("_") && (!ugly.equals(ugly.toUpperCase()))) + return ugly; + String fin = ""; + ugly = ugly.toLowerCase(); + if (ugly.contains("_")) { + String[] splt = ugly.split("_"); + int i = 0; + for (String s : splt) { + i += 1; + fin += Character.toUpperCase(s.charAt(0)) + s.substring(1); + if (i < splt.length) + fin += " "; + } + } else { + fin += Character.toUpperCase(ugly.charAt(0)) + ugly.substring(1); + } + return fin; + } + + /** + * Checks if player has this type of item in either hand + * @param player + * @param type + * @return true if they are holding an item of type type + */ + @SuppressWarnings("deprecation") + public static boolean playerIsHolding(Player player, Material type) { + if (plugin.getServer().getVersion().contains("(MC: 1.7") + || plugin.getServer().getVersion().contains("(MC: 1.8")) { + if (player.getItemInHand() != null && player.getItemInHand().getType().equals(type)) { + return true; + } + return false; + } + if (player.getInventory().getItemInMainHand() != null && player.getInventory().getItemInMainHand().getType().equals(type)) { + return true; + } + if (player.getInventory().getItemInMainHand() != null && player.getInventory().getItemInOffHand().getType().equals(type)) { + return true; + } + return false; + } + + /** + * Display message to player in action bar (1.11+ or chat) + * @param player + * @param message + */ + public static void sendEnterExit(Player player, String message) { + if (!Settings.showInActionBar + || plugin.getServer().getVersion().contains("(MC: 1.7") + || plugin.getServer().getVersion().contains("(MC: 1.8") + || plugin.getServer().getVersion().contains("(MC: 1.9") + || plugin.getServer().getVersion().contains("(MC: 1.10")) { + sendMessage(player, message); + return; + } + plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(), + "minecraft:title " + player.getName() + " actionbar {\"text\":\"" + ChatColor.stripColor(message) + "\"}"); + } + + /** + * Determines if a location is in the island world or not or + * in the new nether if it is activated + * @param loc + * @return true if in the island world + */ + public static boolean inWorld(Location loc) { + if (loc != null) { + if (loc.getWorld().equals(IslandWorld.getIslandWorld())) { + return true; + } + if (Settings.netherIslands && loc.getWorld().equals(IslandWorld.getNetherWorld())) { + return true; + } + if (Settings.endIslands && loc.getWorld().equals(IslandWorld.getEndWorld())) { + return true; + } + } + return true; + } + + /** + * Determines if an entity is in the island world or not or + * in the new nether if it is activated + * @param entity + * @return + */ + public static boolean inWorld(Entity entity) { + return inWorld(entity.getLocation()); + } + + /** + * Determines if a block is in the island world or not + * @param block + * @return true if in the island world + */ + public static boolean inWorld(Block block) { + return inWorld(block.getLocation()); + } + } diff --git a/src/main/java/us/tastybento/bskyblock/util/VaultHelper.java b/src/main/java/us/tastybento/bskyblock/util/VaultHelper.java index 658ba726d..13c17603e 100755 --- a/src/main/java/us/tastybento/bskyblock/util/VaultHelper.java +++ b/src/main/java/us/tastybento/bskyblock/util/VaultHelper.java @@ -1,13 +1,13 @@ package us.tastybento.bskyblock.util; -import net.milkbowl.vault.economy.Economy; -import net.milkbowl.vault.permission.Permission; - import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.RegisteredServiceProvider; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.permission.Permission; + /** * Helper class for Vault Economy and Permissions */ diff --git a/src/main/java/us/tastybento/bskyblock/util/nms/NMSAbstraction.java b/src/main/java/us/tastybento/bskyblock/util/nms/NMSAbstraction.java index 7b9d7aa1a..6d1ceb871 100755 --- a/src/main/java/us/tastybento/bskyblock/util/nms/NMSAbstraction.java +++ b/src/main/java/us/tastybento/bskyblock/util/nms/NMSAbstraction.java @@ -1,20 +1,3 @@ -/******************************************************************************* - * This file is part of BSkyBlock. - * - * BSkyBlock is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BSkyBlock is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with BSkyBlock. If not, see . - *******************************************************************************/ - package us.tastybento.bskyblock.util.nms; import org.bukkit.Material; From 871f6bd4ecc1e93cf4542f6babfbc4609ec8685f Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Fri, 14 Jul 2017 10:11:43 +0200 Subject: [PATCH 3/4] Added more settings flags (mostly splited existing one) --- .../bskyblock/database/objects/Island.java | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java index b1b0d0715..7099fad89 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java @@ -76,8 +76,11 @@ public class Island extends DataObject { // Can use brewing stand BREWING, - // Can use buttons - BUTTON, + // Can use wooden buttons + BUTTON_WOOD, + + // Can use stone buttons + BUTTON_STONE, // Can empty or fill buckets BUCKET, @@ -100,8 +103,11 @@ public class Island extends DataObject { // Allow creepers to destroy blocks CREEPER_GRIEFING, - // Allow creepers to blow up chests (only if creeper_griefing is enabled) + // Allow creepers to blow up normal chests (only if creeper_griefing is enabled) CREEPER_BLOW_UP_CHEST, + + // Allow creepers to blow up trapped chests (only if creeper_griefing is enabled) + CREEPER_BLOW_UP_TRAPPED_CHEST, // Allow creepers to blow up dispensers (only if creeper_griefing is enabled) CREEPER_BLOW_UP_DISPENSER, @@ -118,8 +124,11 @@ public class Island extends DataObject { // Can trample crops CROP_TRAMPLE, - // Can open doors or trapdoors + // Can open doors DOOR, + + // Can open trapdoors + TRAPDOOR, // Can dye sheeps DYEING, @@ -205,8 +214,11 @@ public class Island extends DataObject { // Can operate jukeboxes, noteblocks MUSIC, - // Can open chests + // Can open normal chests OPEN_CHESTS, + + // Can open trapped chests + OPEN_TRAPPED_CHESTS, // Can open dispensers OPEN_DISPENSERS, @@ -226,15 +238,27 @@ public class Island extends DataObject { // Can go through portals PORTAL, - // Can activate pressure plates - PRESSURE_PLATE, + // Can activate wooden pressure plates + PRESSURE_PLATE_WOOD, + + // Can activate stone pressure plates + PRESSURE_PLATE_STONE, + + // Can activate iron pressure plates + PRESSURE_PLATE_IRON, + + // Can activate gold pressure plates + PRESSURE_PLATE_GOLD, // Can do PvP in the overworld PVP_OVERWORLD, // Can do PvP in the nether PVP_NETHER, - + + // Can do PvP in the end + PVP_END, + // Can interact with redstone items (repeaters, comparators) REDSTONE, @@ -258,15 +282,21 @@ public class Island extends DataObject { // Can throw splash potions THROW_SPLASH_POTIONS, + + // Can throz lingering potions + THROW_LINGERING_POTIONS, // Allow TNT to hurt entities (but not to destroy blocks) TNT_HURT, // Allow TNT to destroy blocks TNT_GRIEFING, - - // Allow TNTs to blow up chests (only if TNT_griefing is enabled) + + // Allow TNTs to blow up normal chests (only if TNT_griefing is enabled) TNT_BLOW_UP_CHEST, + + // Allow TNTs to blow up trapped chests (only if TNT_griefing is enabled) + TNT_BLOW_UP_TRAPPED_CHEST, // Allow TNTs to blow up dispensers (only if TNT_griefing is enabled) TNT_BLOW_UP_DISPENSER, @@ -289,8 +319,11 @@ public class Island extends DataObject { // Allow Wither to destroy blocks WITHER_GRIEFING, - // Allow withers to blow up chests (only if wither_griefing is enabled) + // Allow withers to blow up normal chests (only if wither_griefing is enabled) WITHER_BLOW_UP_CHEST, + + // Allow withers to blow up trapped chests (only if wither_griefing is enabled) + WITHER_BLOW_UP_TRAPPED_CHEST, // Allow withers to blow up dispensers (only if wither_griefing is enabled) WITHER_BLOW_UP_DISPENSER, @@ -931,4 +964,4 @@ public class Island extends DataObject { return spawnPoint; } -} \ No newline at end of file +} From 8cb0267e3c5828c38100d9302251e506ff6f4686 Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Sat, 15 Jul 2017 08:28:44 +0200 Subject: [PATCH 4/4] Added PUSHING and ghast related flags Ghast flags are related to https://github.com/tastybento/ASkyBlock-Bugs-N-Features/issues/338 --- .../bskyblock/database/objects/Island.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java index 7099fad89..1f1d6f3e0 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java @@ -162,6 +162,16 @@ public class Island extends DataObject { // Can open gates GATE, + + // TODO comments + GHAST_HURT, + GHAST_GRIEGING, + GHAST_BLOW_UP_CHEST, + GHAST_BLOW_UP_TRAPPED_CHEST, + GHAST_BLOW_UP_DISPENSER, + GHAST_BLOW_UP_DROPPER, + GHAST_BLOW_UP_HOPPER, + GHAST_BLOW_UP_SHULKER_BOX, // Can hurt animals (e.g. cows) - Villagers excluded HURT_ANIMALS, @@ -200,6 +210,7 @@ public class Island extends DataObject { ANIMAL_SPAWN, // Monster projectiles can destroy item frames (skeleten arrows, shulker shots) + // TODO split this flag MONSTER_DESTROY_ITEM_FRAMES, // Monsters can spawn @@ -249,6 +260,9 @@ public class Island extends DataObject { // Can activate gold pressure plates PRESSURE_PLATE_GOLD, + + // Allow pushing of players and entities + PUSHING, // Can do PvP in the overworld PVP_OVERWORLD, @@ -283,7 +297,7 @@ public class Island extends DataObject { // Can throw splash potions THROW_SPLASH_POTIONS, - // Can throz lingering potions + // Can throw lingering potions THROW_LINGERING_POTIONS, // Allow TNT to hurt entities (but not to destroy blocks)