public static void G_SetMovedir(float[] angles, float[] movedir) {
    if (Math3D.VectorEquals(angles, VEC_UP)) {
      Math3D.VectorCopy(MOVEDIR_UP, movedir);
    } else if (Math3D.VectorEquals(angles, VEC_DOWN)) {
      Math3D.VectorCopy(MOVEDIR_DOWN, movedir);
    } else {
      Math3D.AngleVectors(angles, movedir, null, null);
    }

    Math3D.VectorClear(angles);
  }
  /**
   * G_RunFrame
   *
   * <p>Advances the world by Defines.FRAMETIME (0.1) seconds.
   */
  public static void G_RunFrame() {
    int i;
    Entity ent;

    level.framenum++;
    level.time = level.framenum * Constants.FRAMETIME;

    // choose a client for monsters to target this frame
    GameAI.AI_SetSightClient();

    // exit intermissions

    if (level.exitintermission) {
      ExitLevel();
      return;
    }

    //
    // treat each object in turn
    // even the world gets a chance to think
    //

    for (i = 0; i < num_edicts; i++) {
      ent = g_edicts[i];
      if (!ent.inuse) continue;

      level.current_entity = ent;

      Math3D.VectorCopy(ent.s.origin, ent.s.old_origin);

      // if the ground entity moved, make sure we are still on it
      if ((ent.groundentity != null)
          && (ent.groundentity.linkcount != ent.groundentity_linkcount)) {
        ent.groundentity = null;
        if (0 == (ent.flags & (Constants.FL_SWIM | Constants.FL_FLY))
            && (ent.svflags & Constants.SVF_MONSTER) != 0) {
          ClientMonsterMethods.M_CheckGround(ent);
        }
      }

      if (i > 0 && i <= maxclients.value) {
        PlayerClient.ClientBeginServerFrame(ent);
        continue;
      }

      G_RunEntity(ent);
    }

    // see if it is time to end a deathmatch
    CheckDMRules();

    // see if needpass needs updated
    CheckNeedPass();

    // build the playerstate_t structures for all players
    ClientEndServerFrames();
  }