/set_time command #107

Closed
Nisc3d opened this Issue May 29, 2014 · 13 comments

Comments

Projects
None yet
4 participants
@Nisc3d

Nisc3d commented May 29, 2014

Maybe add a set_time command.
Syntax: /set_time (0:6:12:18)
The numbers are the times in the default.cs.

@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx May 29, 2014

Member

I already had a similar idea.
This would need current time system to be redone.
AFAIK it's based on ticks since world was created.

We could use a mapping that repeats each day.
Maybe just daytime in minutes?
This would allow something like:

  • /time 0 --> 00:00
  • /time 300 --> 05:00
  • /time 1200 --> 20:00
Member

croxxx commented May 29, 2014

I already had a similar idea.
This would need current time system to be redone.
AFAIK it's based on ticks since world was created.

We could use a mapping that repeats each day.
Maybe just daytime in minutes?
This would allow something like:

  • /time 0 --> 00:00
  • /time 300 --> 05:00
  • /time 1200 --> 20:00

@croxxx croxxx added suggestion and removed refactoring labels May 29, 2014

@Nisc3d Nisc3d changed the title from [Suggestion] /set_time command to /set_time command May 29, 2014

@EmilSayahi

This comment has been minimized.

Show comment
Hide comment
@EmilSayahi

EmilSayahi Nov 19, 2014

Contributor

This is really, really needed.

Contributor

EmilSayahi commented Nov 19, 2014

This is really, really needed.

@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Jan 18, 2015

Member

Inplementing this needs a complete overhaul of how time is handled in MD currently.

  • Adaption of SunMoonRenderer
  • Adaption of time saved in savegames
  • eventually more I didn't think of right now...
Member

croxxx commented Jan 18, 2015

Inplementing this needs a complete overhaul of how time is handled in MD currently.

  • Adaption of SunMoonRenderer
  • Adaption of time saved in savegames
  • eventually more I didn't think of right now...
@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Jan 18, 2015

Member

Current time is static based on time since creation of world (taken from Server.cs):

public class GameTime
{
    public long Ticks;
    public int TicksPerSecond = 64;
    public double GameYearRealHours = 24;
    public double GameDayRealHours = 1;
    public double HourTotal // 0 - 23
    {
        get
        {
            return ((double)Ticks / TicksPerSecond) / (GameDayRealHours * 60 * 60);
        }
    }
    public double YearTotal
    {
        get
        {
            return ((double)Ticks / TicksPerSecond) / (GameYearRealHours * 60 * 60);
        }
    }
}

This is also very closely related to server simulation time. It should be independent, though as game time might be variable.

@exemd and I spoke about this some time ago.
The discussion ended up on an interesting concept of chunk versioning instead of absolute time, but that's another issue. 😀

Current system isn't fully functional anyway. If changing duration of days things get buggy.

Member

croxxx commented Jan 18, 2015

Current time is static based on time since creation of world (taken from Server.cs):

public class GameTime
{
    public long Ticks;
    public int TicksPerSecond = 64;
    public double GameYearRealHours = 24;
    public double GameDayRealHours = 1;
    public double HourTotal // 0 - 23
    {
        get
        {
            return ((double)Ticks / TicksPerSecond) / (GameDayRealHours * 60 * 60);
        }
    }
    public double YearTotal
    {
        get
        {
            return ((double)Ticks / TicksPerSecond) / (GameYearRealHours * 60 * 60);
        }
    }
}

This is also very closely related to server simulation time. It should be independent, though as game time might be variable.

@exemd and I spoke about this some time ago.
The discussion ended up on an interesting concept of chunk versioning instead of absolute time, but that's another issue. 😀

Current system isn't fully functional anyway. If changing duration of days things get buggy.

@TobiMob

This comment has been minimized.

Show comment
Hide comment
@TobiMob

TobiMob Feb 1, 2015

Contributor

I created this branch with a prototype for a more flexible TimeOfDay system.

Only Server.cs is changed and those two variables are the center of it:

    //current time of day
    private TimeSpan _tsIngameTime = new TimeSpan(9, 0, 0);// 9:00

    //This changes how fast time goes on
    //0 freezes the time
    //can be negative to let time run backwards
    private int _nIngameSecondsEveryRealTimeSecond = 600;

Changes:

_tsIngameTime as the current TimeOfDay
Decouples the ServerTicks from the IngameTime,
to update the time independent from the Server Ticks.
A TimeSpan can hold ~10,600,000 days (~29,000 years)

-Register SetTime-Command
-Change _tsIngameTime-Variable
-Profit.

_nIngameSecondsEveryRealTimeSecond int defines how fast time goes by.
The SunMoonRenderer works pretty solid.
So we can let the time run forward, backward or freeze it.

_nIngameSecondsEveryRealTimeSecond with a value of 600 still looks good for me,
but as the value increases, the sun starts to jump backwards.
Looks like some sort of interpolation is needed, to make faster clocks look smooth.

Server Ticks are no longer saved, instead TimeOfDay is saved.
(Discuss please)
Is there still any need to save the server-ticks?


This changes only affect the Server. It should also work with older clients.
I think _tsIngameTime and _nIngameSecondsEveryRealTimeSecond are a good way to go.

Any additions or concerns about this direction?

Contributor

TobiMob commented Feb 1, 2015

I created this branch with a prototype for a more flexible TimeOfDay system.

Only Server.cs is changed and those two variables are the center of it:

    //current time of day
    private TimeSpan _tsIngameTime = new TimeSpan(9, 0, 0);// 9:00

    //This changes how fast time goes on
    //0 freezes the time
    //can be negative to let time run backwards
    private int _nIngameSecondsEveryRealTimeSecond = 600;

Changes:

_tsIngameTime as the current TimeOfDay
Decouples the ServerTicks from the IngameTime,
to update the time independent from the Server Ticks.
A TimeSpan can hold ~10,600,000 days (~29,000 years)

-Register SetTime-Command
-Change _tsIngameTime-Variable
-Profit.

_nIngameSecondsEveryRealTimeSecond int defines how fast time goes by.
The SunMoonRenderer works pretty solid.
So we can let the time run forward, backward or freeze it.

_nIngameSecondsEveryRealTimeSecond with a value of 600 still looks good for me,
but as the value increases, the sun starts to jump backwards.
Looks like some sort of interpolation is needed, to make faster clocks look smooth.

Server Ticks are no longer saved, instead TimeOfDay is saved.
(Discuss please)
Is there still any need to save the server-ticks?


This changes only affect the Server. It should also work with older clients.
I think _tsIngameTime and _nIngameSecondsEveryRealTimeSecond are a good way to go.

Any additions or concerns about this direction?

@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Feb 1, 2015

Member

Server Ticks in chunks is used to determine when a chunk last changed, I think. So changing this maybe requires some extra work.

SunMoonRenderer already handles such stuff? Good.

  • Does changing time during runtime work with this?
  • Can you change speed of time passing without having to reconnect?
  • What happens if client gets disconnected from server? Does time still pass for them?

Personally, I'd like a system that repeats each day instead of a continuous one more. But that's my opinion.

So far: good concept

Member

croxxx commented Feb 1, 2015

Server Ticks in chunks is used to determine when a chunk last changed, I think. So changing this maybe requires some extra work.

SunMoonRenderer already handles such stuff? Good.

  • Does changing time during runtime work with this?
  • Can you change speed of time passing without having to reconnect?
  • What happens if client gets disconnected from server? Does time still pass for them?

Personally, I'd like a system that repeats each day instead of a continuous one more. But that's my opinion.

So far: good concept

@TobiMob

This comment has been minimized.

Show comment
Hide comment
@TobiMob

TobiMob Feb 1, 2015

Contributor

Most of the stuff was already implemented.
As far as I understand, it works currently like this:

If one of these occurs:

  • Client connects
  • TimeOfDay changes to a new sunlevel (15 ingame minutes)

then:
Server.NotifySeason(clientID) is called.
Which sends a Packet_ServerSeason to the client.
The package contains the TimeOfDay and the "speed of time" (meh).
This information is forwarded to the SunMoonRenderer.
The SunMoonRenderer sets its internal clock to the given time and starts running with the given speed,
until noted otherwise.

So the only thing that misses is a NotifySeason() call after a "speed of time" changes..
And maybe NotifySeason() should be renamed to NotifyTime() or such.

Contributor

TobiMob commented Feb 1, 2015

Most of the stuff was already implemented.
As far as I understand, it works currently like this:

If one of these occurs:

  • Client connects
  • TimeOfDay changes to a new sunlevel (15 ingame minutes)

then:
Server.NotifySeason(clientID) is called.
Which sends a Packet_ServerSeason to the client.
The package contains the TimeOfDay and the "speed of time" (meh).
This information is forwarded to the SunMoonRenderer.
The SunMoonRenderer sets its internal clock to the given time and starts running with the given speed,
until noted otherwise.

So the only thing that misses is a NotifySeason() call after a "speed of time" changes..
And maybe NotifySeason() should be renamed to NotifyTime() or such.

@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Feb 1, 2015

Member

Sounds quite straightforward.
Renaming definitely is a good idea. It doesn't have that much to do with seasons 😄

Member

croxxx commented Feb 1, 2015

Sounds quite straightforward.
Renaming definitely is a good idea. It doesn't have that much to do with seasons 😄

@TobiMob

This comment has been minimized.

Show comment
Hide comment
@TobiMob

TobiMob Feb 2, 2015

Contributor

Doesn't seem to complicated yet 😃.

How about storing the days?
The passed days are already stored in the Timespan.
They could be used for seasons, a farming mod, three growth or whatever.

Possible server command:
Useful could be:

  • set time relative
  • set time absolute
  • set time speed

Commands could start with a /time then have a operation and then a value

/time set (d.)hh:mm:ss
Set time to value. (d.) possible for days

/time add (-)(d.)hh:mm:ss
add/subtract given time to the current time

/time speed x
for every realtime second x ingame seconds pass.

Contributor

TobiMob commented Feb 2, 2015

Doesn't seem to complicated yet 😃.

How about storing the days?
The passed days are already stored in the Timespan.
They could be used for seasons, a farming mod, three growth or whatever.

Possible server command:
Useful could be:

  • set time relative
  • set time absolute
  • set time speed

Commands could start with a /time then have a operation and then a value

/time set (d.)hh:mm:ss
Set time to value. (d.) possible for days

/time add (-)(d.)hh:mm:ss
add/subtract given time to the current time

/time speed x
for every realtime second x ingame seconds pass.

@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Feb 2, 2015

Member

Good ideas for the command syntax. 👍
I also found out that while chunksseenTime[] values are assigned, they never seem to be used in server. Maybe they can simply be thrown out (referring to the ones in ClientOnServer class).

I don't know if it is affected, but server.simulationcurrentframe is used in ServerChunk class, too:

[ProtoContract()]
public class ServerChunk
{
    [ProtoMember(1, IsRequired = false)]
    public byte[] dataOld;
    [ProtoMember(6, IsRequired = false)]
    public ushort[] data;
    [ProtoMember(2, IsRequired = false)]
    public long LastUpdate;
    [ProtoMember(3, IsRequired = false)]
    public bool IsPopulated;
    [ProtoMember(4, IsRequired = false)]
    public int LastChange;
    public bool DirtyForSaving;
    [ProtoMember(5, IsRequired = false)]
    public List<Monster> Monsters = new List<Monster>();
    [ProtoMember(7, IsRequired = false)]
    public int EntitiesCount;
    [ProtoMember(8, IsRequired = false)]
    public ServerEntity[] Entities;
}

Or is that time stuff completely independent then? Would certainly be cool.

Member

croxxx commented Feb 2, 2015

Good ideas for the command syntax. 👍
I also found out that while chunksseenTime[] values are assigned, they never seem to be used in server. Maybe they can simply be thrown out (referring to the ones in ClientOnServer class).

I don't know if it is affected, but server.simulationcurrentframe is used in ServerChunk class, too:

[ProtoContract()]
public class ServerChunk
{
    [ProtoMember(1, IsRequired = false)]
    public byte[] dataOld;
    [ProtoMember(6, IsRequired = false)]
    public ushort[] data;
    [ProtoMember(2, IsRequired = false)]
    public long LastUpdate;
    [ProtoMember(3, IsRequired = false)]
    public bool IsPopulated;
    [ProtoMember(4, IsRequired = false)]
    public int LastChange;
    public bool DirtyForSaving;
    [ProtoMember(5, IsRequired = false)]
    public List<Monster> Monsters = new List<Monster>();
    [ProtoMember(7, IsRequired = false)]
    public int EntitiesCount;
    [ProtoMember(8, IsRequired = false)]
    public ServerEntity[] Entities;
}

Or is that time stuff completely independent then? Would certainly be cool.

@TobiMob

This comment has been minimized.

Show comment
Hide comment
@TobiMob

TobiMob Feb 11, 2015

Contributor

I would like the changes to only affect:

  • Server.NotifySeason() [or Server.NotifyTime()]
  • ModManager.GetCurrentHourTotal();
  • ModManager.GetCurrentYearTotal();

that should be enough.
(Anything else that needs to be affected by the TimeOfDay?)

ChunkSimulation for example uses the Server.simulationcurrentframe, and I would like to keep it that way. Since it would screw up, if we stop the time.

  • Server.NotifySeason() [Server.NotifyTime()]
    Should be called depending on the TimeOfDay-Variable.
  • ModManager.GetCurrentHourTotal()
    Should return TimeOfDay.Hours
  • ModManager.GetCurrentYearTotal();
    Maybe a TimeOfDay.Days / DaysPerYear
    (and add a ModManager.SetDaysPerYear())

This could be enough, to make setting the TimeOfDay possible (without breaking any existing stuff).

In that turn, I would like to mark the SetGameYearRealHours in the Modmanager as obsolete.
I think a Year calculation based on Days would be more straight forward.
It could be changed to call the new SetDaysPerYear() Method, to let existing mods still work (somehow).

//Sets the number of real hours that one ingame year takes
[Obsolete("use SetDaysPerYear() instead")]
SetGameYearRealHours(double hours);
{
   SetDaysPerYear(hours);
}

///Sets the number of ingame-days a ingame-year has 
SetDaysPerYear(double days)
Contributor

TobiMob commented Feb 11, 2015

I would like the changes to only affect:

  • Server.NotifySeason() [or Server.NotifyTime()]
  • ModManager.GetCurrentHourTotal();
  • ModManager.GetCurrentYearTotal();

that should be enough.
(Anything else that needs to be affected by the TimeOfDay?)

ChunkSimulation for example uses the Server.simulationcurrentframe, and I would like to keep it that way. Since it would screw up, if we stop the time.

  • Server.NotifySeason() [Server.NotifyTime()]
    Should be called depending on the TimeOfDay-Variable.
  • ModManager.GetCurrentHourTotal()
    Should return TimeOfDay.Hours
  • ModManager.GetCurrentYearTotal();
    Maybe a TimeOfDay.Days / DaysPerYear
    (and add a ModManager.SetDaysPerYear())

This could be enough, to make setting the TimeOfDay possible (without breaking any existing stuff).

In that turn, I would like to mark the SetGameYearRealHours in the Modmanager as obsolete.
I think a Year calculation based on Days would be more straight forward.
It could be changed to call the new SetDaysPerYear() Method, to let existing mods still work (somehow).

//Sets the number of real hours that one ingame year takes
[Obsolete("use SetDaysPerYear() instead")]
SetGameYearRealHours(double hours);
{
   SetDaysPerYear(hours);
}

///Sets the number of ingame-days a ingame-year has 
SetDaysPerYear(double days)
@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Feb 13, 2015

Member

@TobiMob You're right, time should be separate.
I can't think of anything else that would need to be altered.

I like the idea of days per year.

Also we could simply remove the SetGameYearRealHours() method.
The only place it is used in is the game core mods.
Also I don't know any mod that uses it apart from one I wrote (which is basically a copy of the season change code).

Member

croxxx commented Feb 13, 2015

@TobiMob You're right, time should be separate.
I can't think of anything else that would need to be altered.

I like the idea of days per year.

Also we could simply remove the SetGameYearRealHours() method.
The only place it is used in is the game core mods.
Also I don't know any mod that uses it apart from one I wrote (which is basically a copy of the season change code).

@croxxx

This comment has been minimized.

Show comment
Hide comment
@croxxx

croxxx Aug 4, 2015

Member

Implemented in 468d38e and following commits.
Maybe still requires some work on command input formatting.

Member

croxxx commented Aug 4, 2015

Implemented in 468d38e and following commits.
Maybe still requires some work on command input formatting.

@croxxx croxxx closed this Aug 4, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment