Skip to content

Commit

Permalink
Changes for experience and level systems, see #87
Browse files Browse the repository at this point in the history
Add player experience and levels
Add Experience Orb entity
Add /givexp command
  • Loading branch information
taugit committed Sep 15, 2012
1 parent e142394 commit 79a3976
Show file tree
Hide file tree
Showing 10 changed files with 314 additions and 9 deletions.
1 change: 1 addition & 0 deletions Chraft.PluginSystem/Entity/IPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ public interface IPlayer : ILivingEntity
bool CanUseCommand(string command);
string GetPlayerPrefix();
string GetPlayerSuffix();
void AddExperience(short amount);
}
}
1 change: 1 addition & 0 deletions Chraft.Plugins.Commands/Chraft.Plugins.Commands.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<Compile Include="CmdTime.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CmdVersion.cs" />
<Compile Include="CmdGiveXP.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Chraft.PluginSystem\Chraft.PluginSystem.csproj">
Expand Down
3 changes: 2 additions & 1 deletion Chraft.Plugins.Commands/ChraftCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public void Initialize()
new CmdSpawnMob(this),
new CmdMute(this),
new CmdSetHealth(this),
new CmdVersion(this)
new CmdVersion(this),
new CmdGiveXP(this)
};
}

Expand Down
129 changes: 129 additions & 0 deletions Chraft.Plugins.Commands/CmdGiveXP.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#region C#raft License
// This file is part of C#raft. Copyright C#raft Team
//
// C#raft is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#endregion

using System.Linq;
using Chraft.PluginSystem;
using Chraft.PluginSystem.Commands;
using Chraft.PluginSystem.Net;
using Chraft.Utilities.Misc;

namespace Chraft.Plugins.Commands
{
public class CmdGiveXP : IClientCommand
{
public CmdGiveXP(IPlugin plugin)
{
Iplugin = plugin;
}

public IClientCommandHandler ClientCommandHandler { get; set; }

public void Use(IClient client, string commandName, string[] tokens)
{
short amount;
IClient target;

if (tokens.Length == 1)
{
if (short.TryParse(tokens[0], out amount))
{
client.GetOwner().AddExperience(amount);
client.SendMessage(string.Format("{0}You has been granted with {1} exp", ChatColor.Red, amount));
return;
}
Help(client);
return;
}

if (tokens.Length == 2)
{
IClient[] matchedClients = client.GetServer().GetClients(tokens[0]).ToArray();
if (matchedClients.Length < 1)
{
client.SendMessage("Unknown Player");
return;
}
if (matchedClients.Length == 1)
{
target = matchedClients[0];
}
else
{
int exactMatchClient = -1;
for (int i = 0; i < matchedClients.Length; i++)
{
if (matchedClients[i].GetOwner().DisplayName.ToLower() == tokens[0].ToLower())
exactMatchClient = i;
}

// If we found the player with the exactly same name - he is our target
if (exactMatchClient != -1)
{
target = matchedClients[exactMatchClient];
}
else
{
// We do not found a proper target and aren't going to randomly punish anyone
client.SendMessage("More than one player found. Provide the exact name.");
return;
}
}

if (short.TryParse(tokens[1], out amount))
{
target.GetOwner().AddExperience(amount);
target.SendMessage(string.Format("{0}{1} has been granted with {2} exp", ChatColor.Red, target.GetOwner().DisplayName, amount));
}
else
{
Help(client);
}
return;
}

Help(client);
}

public void Help(IClient client)
{
client.SendMessage("/givexp [Player] <amount> - gives the player an experience");
}

public string Name
{
get { return "givexp"; }
set { }
}

public string Shortcut
{
get { return ""; }
}

public CommandType Type
{
get { return CommandType.Mod; }
}

public string Permission
{
get { return "chraft.givexp"; }
}

public IPlugin Iplugin { get; set; }
}
}
1 change: 1 addition & 0 deletions Chraft.Utilities/Chraft.Utilities.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<Compile Include="Misc\CommandType.cs" />
<Compile Include="Misc\DamageCause.cs" />
<Compile Include="Misc\Direction.cs" />
<Compile Include="Misc\Experience.cs" />
<Compile Include="Misc\Hash.cs" />
<Compile Include="Misc\Http.cs" />
<Compile Include="Misc\MobType.cs" />
Expand Down
70 changes: 70 additions & 0 deletions Chraft.Utilities/Misc/Experience.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#region C#raft License
// This file is part of C#raft. Copyright C#raft Team
//
// C#raft is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#endregion

namespace Chraft.Utilities.Misc
{
public static class Experience
{
public static short GetLevel(short experience)
{
short level = 0;
if (experience <= 16)
return level;

short toTheNext = ExpToNextLevel(level);
while (experience >= toTheNext)
{
level++;
experience -= toTheNext;
toTheNext = ExpToNextLevel(level);
}

return level;
}

public static short GetExperience(short level)
{
if (level <= 0)
return 0;

if (level >= 1 && level <= 15)
return (short)System.Math.Min(short.MaxValue, 17 * level);

if (level >= 16 && level <= 30)
return (short)System.Math.Min(short.MaxValue, 1.5 * (level * level) - (29.5 * level) + 360);

// Levels 31+
return (short)System.Math.Min(short.MaxValue, 3.5 * (level * level) - (151.5 * level) + 2220);
}

public static short ExpToNextLevel(short currentLevel)
{
// TODO: Proper handling of negative level
if (currentLevel < 0)
return 17;

if (currentLevel >= 0 && currentLevel <= 14)
return 17;

if (currentLevel >= 15 && currentLevel <= 29)
return (short)System.Math.Min(short.MaxValue, 3 * currentLevel - 28);

// Levels 30+
return (short)System.Math.Min(short.MaxValue, 7 * currentLevel - 148);
}
}
}
1 change: 1 addition & 0 deletions Chraft/Chraft.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
<Compile Include="Entity\Animal.cs" />
<Compile Include="Entity\EntityBase.cs" />
<Compile Include="Entity\EnumCreatureType.cs" />
<Compile Include="Entity\ExpOrbEntity.cs" />
<Compile Include="Entity\ItemEntity.cs" />
<Compile Include="Entity\Monster.cs" />
<Compile Include="Interfaces\Containers\ContainerFactory.cs" />
Expand Down
46 changes: 46 additions & 0 deletions Chraft/Entity/ExpOrbEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#region C#raft License
// This file is part of C#raft. Copyright C#raft Team
//
// C#raft is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#endregion

using Chraft.Utilities.Coords;
using Chraft.World;

namespace Chraft.Entity
{
public class ExpOrbEntity : EntityBase
{
public short Experience { get; protected set; }

public ExpOrbEntity(Server server, int entityId, short exp)
: base(server, entityId)
{
Height = 0.5f;
Width = 0.5f;
Experience = exp;
World = server.GetDefaultWorld() as WorldManager;
}

protected override void DoUpdate()
{
base.DoUpdate();

PushOutOfBlocks(new AbsWorldCoords(Position.X, (BoundingBox.Minimum.Y + BoundingBox.Maximum.Y) / 2.0, Position.Z));
var chunk = World.GetChunk(UniversalCoords.FromAbsWorld(Position));
if (chunk == null)
return;
}
}
}
58 changes: 50 additions & 8 deletions Chraft/Entity/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,26 @@
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;
using Chraft.Commands;
using Chraft.Interfaces;
using Chraft.Net.Packets;
using Chraft.PluginSystem;
using Chraft.PluginSystem.Args;
using Chraft.PluginSystem.Commands;
using Chraft.PluginSystem.Entity;
using Chraft.PluginSystem.Event;
using Chraft.PluginSystem.Item;
using Chraft.PluginSystem.Net;
using Chraft.PluginSystem.World;
using Chraft.Plugins.Events;
using Chraft.Utilities;
using Chraft.Utilities.Blocks;
using Chraft.Utilities.Config;
using Chraft.Utilities.Coords;
using Chraft.Utilities.Misc;
using Chraft.Utils;
using Chraft.World;
using Chraft.Net;
using Chraft.World.Blocks;

namespace Chraft.Entity
{
Expand All @@ -64,6 +58,8 @@ public override string Name
public TimeSpan SaveSpan = TimeSpan.FromSeconds(60.0);
public int ChangesToSave;

public int Experience { get; protected set; }

private Client _client;

public Client Client
Expand Down Expand Up @@ -295,8 +291,11 @@ internal void UpdateEntities()
_client.SendCreateEntity(e);
LoadedEntities.TryAdd(e.EntityId, e);
}
if (Health > 0 && e is ItemEntity && Math.Abs(e.Position.X - Position.X) < 1 && Math.Abs(e.Position.Y - Position.Y) < 1 && Math.Abs(e.Position.Z - Position.Z) < 1)
PickupItem((ItemEntity)e);
if (Health > 0 && Math.Abs(e.Position.X - Position.X) < 1 && Math.Abs(e.Position.Y - Position.Y) < 1 && Math.Abs(e.Position.Z - Position.Z) < 1)
if (e is ItemEntity)
PickupItem((ItemEntity)e);
else if (e is ExpOrbEntity)
PickupExpOrb((ExpOrbEntity)e);
}

Queue<int> entitiesToRemove = new Queue<int>();
Expand Down Expand Up @@ -581,6 +580,49 @@ internal void HandleRespawn()
Server.AddEntity(this);
}

public void SendUpdateExperience()
{
var exp = (short)(Experience > short.MaxValue ? short.MaxValue : Experience);
var level = Utilities.Misc.Experience.GetLevel(exp);
var nextLevelExp = Utilities.Misc.Experience.ExpToNextLevel(level);
var thisLevelExp = Utilities.Misc.Experience.GetExperience(level);
float expOnBar = (exp - thisLevelExp)/(float)nextLevelExp;

Client.SendPacket(new ExperiencePacket
{
Experience = expOnBar,
Level = level,
TotExperience = exp,
});
}

public void AddExperience(short amount)
{
if (amount <= 0)
return;
long newExp = Experience + amount;
if (newExp > Int32.MaxValue)
newExp = Int32.MaxValue;
Experience = (int)newExp;
SendUpdateExperience();
}

private void PickupExpOrb(ExpOrbEntity orb)
{
if (Server.GetEntityById(orb.EntityId) == null)
return;

Server.SendPacketToNearbyPlayers(orb.World, UniversalCoords.FromAbsWorld(orb.Position), new CollectItemPacket
{
EntityId = orb.EntityId,
PlayerId = EntityId
});

Server.RemoveEntity(orb);

AddExperience(orb.Experience);
}

private void PickupItem(ItemEntity item)
{
if (Server.GetEntityById(item.EntityId) == null)
Expand Down
Loading

0 comments on commit 79a3976

Please sign in to comment.